Laden...

SQL Reports - Berichtsparameter

Erstellt von trib vor 15 Jahren Letzter Beitrag vor 15 Jahren 759 Views
T
trib Themenstarter:in
708 Beiträge seit 2008
vor 15 Jahren
SQL Reports - Berichtsparameter

verwendetes Datenbanksystem: SQL 2005 SP2 / VS 2005

Hallo zusammen,

ich habe ein eher allgemeines Problem mit SQL.
Genauer SQL Reporting.
Anhand von Berichtsparametern möchte ich Datensätze filtern bzw. wenn kein Parameter angegeben wird, möchte ich alle Daten sehen.

Jeder Filter der leer gelassen wird, muss mit einem „OR“ abgefangen werden um alle Datensätze ungefiltert zu erhalten.

([Tabelle].[Feld] = @Filter) OR (@Filter = NULL)

Genau dieses böse „OR“ nimmt das gesamte SQL Statement, kopiert es einmal davor und einmal dahinter (eben einmal das gesamte Statement mit Filter & einmal mit Parameter=NULL).

Aufgrund der vielen SubSelects(28stk) und der 12 Filterparameter kämen ich nach Adam Riese auf den 336fachen Quellcode.
Das kann ja nicht die Lösung sein…

Abgesehen davon, das wenn man diesen Berichtsparametern eine Tabelle hinterlegt, hat man garnicht die Möglichkeit einen Leeren Wert zu übergeben und alle Datensätze ungefilter anzeigen zu lassen.

Bin für jede Hilfe Dankbar, auch wenn das ganze (noch) nicht viel mit C# zu tun hat 🙂

Gruß,
TriB

H
208 Beiträge seit 2008
vor 15 Jahren

Wenn ich das richtig verstehe hast Du eine Abfrage mit theoretisch 12 Parametern, die aber in allen möglichen beliebigen Kombinationen gesetzt/nicht gesetzt sein können und dann entsprechend in der Where-Bedingung der Abfrage berücksichtigt/nicht berücksichtigt werden dürfen?

Solche Sachen versuche ich immer in einer Stored Procedure mit Hilfe einer Temptabelle/Tabellenvariablen häppchenweise zu bearbeiten.

Als simples Beispiel: ich will alle Aufträge aus den letzten 3 Monaten, entweder alle oder nur die mit einer bestimmten Farbe.

Ich deklariere mir eine Tabellenvariable die hinterher zurückgegeben wird:


declare @tmp table (
  AuftragsNr int,
  Farbe varchar(20)
)

Ich füge ALLE Aufträge der letzten 3 Monate ein:


insert into @tmp (AuftragsNr, Farbe)
select AuftragsNr, Farbe from tbAuftraege where Datum > '2008-03-19'

Falls der Parameter "Farbe" gesetzt ist lösche ich alles mit der falschen Farbe einfach wieder raus:


if @FarbFilter <> ' alle'
begin
  delete from @tmp where Farbe <> @FarbFilter
end

Und das mache ich dann halt für jeden einzelnen Filter so.
Und am Ende gebe ich meine gesamte Tabellenvariable zurück, als Datenquelle meines Berichtes:

select * from @tmp

Natürlich kann man das auch nicht in allen Fällen so anwenden, bei einer einigermaßen großen Datenmenge geht das nur wenn man zumindest einen oder zwei Filter hat die IMMER gesetzt sind, so daß man dann erstmal die Menge der Daten begrenzen kann die man einfügt.
So wie in meinem Beispiel das Datum, denn die Aufträge der letzten 3 Monate sind eine überschaubare Menge.

Das gleiche Prinzip nutze ich auch wenn ich Daten aus vielen verschiedenen Tabellen holen muß (vor allem in Verbindung mit Filtern) und eine Abfrage mit 15 Joins zu langsam ist.

  • zuerst nur das nötigste in die Temptabelle (z.B. Auftragsnr)
  • Werte aus einer anderen Tabelle holen
  • diese sofort filtern und alle nicht benötigten Daten aus der Temptabelle löschen
  • weitere Werte aus einer weiteren Tabelle holen
  • diese wieder sofort filtern
    usw.
    Wenn ich abschätzen kann welche Filter am meisten Daten eliminieren hole ich mir die zuerst.
    Wenn ich irgendwelche Felder aus anderen Tabellen dazuholen muß die nie gefiltert werden, dann mache ich das ganz zum Schluß wenn ich schon alles gelöscht habe was geht.

Und zu der Tabelle als Berichtsparameter und dem leeren Wert - um mein Beispiel von oben mal fortzuführen würde ich für den @Farbfilter z.B. eine Tabelle mit Farben hinterlegen.
In der Tabelle ist natürlich normalerweise keine Farbe "alle", also füge ich meiner Abfrage einfach mit UNION eine hinzu:


select ' alle'
union
select Farbe from tbFarben
order by Farbe

Dadurch daß ' alle' mit einem Leerzeichen anfängt und ich nach Farbe sortiere, ist ' alle' automatisch der erste Wert in der Liste und fällt dem Benutzer sofort ins Auge.

T
trib Themenstarter:in
708 Beiträge seit 2008
vor 15 Jahren

Boahr, SUPER! Dank dir vielmals.

Habe gerade die " alle" Geschichte ausprobiert und sie funktioniert prima.
An das Stored Procedure werde ich mich dann aber erst nach dem Wochenende wagen 😉
Hast genau mein Problem verstanden und super erklärt.

Ich muss mir nur überlegen wie ich das am sinnvollsten in diese ganzen sub selects einbaue. Evtl. kann ich ja ähnliche Abfragen in einem Rutsch mit dem delete bearbeiten.

Schönes Wochenende,
TriB

H
208 Beiträge seit 2008
vor 15 Jahren

Ähnliche Abfragen mit einem Rutsch? Nicht nötig.
Dadurch daß wir diese ganzen Operationen in einer Tabellenvariablen (also eine Variable im Hauptspeicher) machen sind die rasend schnell, deshalb kann man den Overhead durch die im Extremfall 12 einzelnen Delete-Abfragen vernachlässigen.

Deshalb nutze ich wirklich für jeden Filter eine eigene Abfrage.
Also z.B. so:


if @FarbFilter <> ' alle'
begin
  delete from @tmp where Farbe <> @FarbFilter
end

if @MaxLaenge > 0
begin
  delete from @tmp where Laenge > @MaxLaenge
end

usw.

Natürlich, wenn Du irgendwelche Sachen hast wo es sich anbietet kannst Du die ruhig zusammen mit einer Delete-Abfrage wegputzen, aber in den meisten Fällen wirst Du es eh einzeln machen müssen weil die Kombination welcher Filter gesetzt ist und welcher nicht sich ja jedes Mal ändern kann.