Abfragen auf gleiche Datensatzmengen mit "Where-Filtern"
Lude
- datenbank
Hi,
habe eine "SQL-Frage". Und zwar geht es mir darum, bei Abfragen auf gleiche Datensatzmengen, die aber unterschiedliche "Where-Klauseln" besitzen, Code-Redundanzen zu vermeiden.
Beispiel:
select
-- lange "Select-Argumentenliste"
join
-- lange "Join-Datentabellenliste"
where
(x = y)
select
-- lange mit der o.g. Abfrage identische "Select-Argumentenliste"
join
-- lange mit der o.g. Abfrage identische "Join-Datentabellenliste"
where
(y = z)
-- u.s.w.
Beispielsweise stecken in einer SQL-Routine 6 solche Abfragen. Hier moechte ich den "Select-Join"-Block nur einmal haben und nicht sechsmal.
Was macht man denn da ueblicherweise? Beispielsweise CASE..WHEN..THEN bei 'T-SQL' ueberzeugt mich nicht. Temporaere Tabellen?
Gruss,
Lude
Hallo Lude!
Beispiel:
select
-- lange "Select-Argumentenliste"
join
-- lange "Join-Datentabellenliste"
where
(x = y)select
-- lange mit der o.g. Abfrage identische "Select-Argumentenliste"
join
-- lange mit der o.g. Abfrage identische "Join-Datentabellenliste"
where
(y = z)
Was macht man denn da ueblicherweise? Beispielsweise CASE..WHEN..THEN bei 'T-SQL' ueberzeugt mich nicht. Temporaere Tabellen?
Eigentlich müßte es doch mit
where (x = y) || (y = z) ...
gehen, oder funktioniert das nicht bzw. habe ich Dein Problem nicht ganz verstanden?
(http://www.mysql.com/doc/en/Logical_Operators.html)
MfG
Götz
Hi,
Was macht man denn da ueblicherweise? Beispielsweise CASE..WHEN..THEN bei 'T-SQL' ueberzeugt mich nicht. Temporaere Tabellen?
Eigentlich müßte es doch mit
where (x = y) || (y = z) ...
gehen, oder funktioniert das nicht bzw. habe ich Dein Problem nicht ganz verstanden?
ich hatte mich schlecht ausgedrueckt. Die Routine mit den 6 Abfragen soll in Abhaengigkeit einer Bedingung (ein erhaltener Parameter, der von ihr ausgewertet wird) eine von diesen 6 Abfragen ausfuehren.
Gruss,
Lude
Hallo Lude!
Die Routine mit den 6 Abfragen soll in Abhaengigkeit einer Bedingung (ein erhaltener Parameter, der von ihr ausgewertet wird) eine von diesen 6 Abfragen ausfuehren.
Ah. ok. Das hat dann aber weniger mit SQL zu tun, oder?
Welche Abfrage ausgeführt wird entscheidet ja dann diese Routine, und nicht das SQL-Statement selbst.
Irgendwie werd ich immer noch nciht so richtig schlau daraus ...
MfG
Götz
Hi,
Ah. ok. Das hat dann aber weniger mit SQL zu tun, oder?
Welche Abfrage ausgeführt wird entscheidet ja dann diese Routine, und nicht das SQL-Statement selbst.
Irgendwie werd ich immer noch nciht so richtig schlau daraus ...
SQL kommt in einigen Dialekten mit einer Programmflusskontrollsprache. Ob MySQL sowas kennt weiss ich nicht.
(Ausserhalb von SQL, also in der umgebenden Programmlogik haette ich natuerlich kein Problem)
Gruss,
Lude
Hi Lude,
SQL kommt in einigen Dialekten mit einer Programmflusskontrollsprache. Ob MySQL sowas kennt weiss ich nicht.
die Frage ist, was Du genau willst, und woran Du feststellst ob ein Parameter existiert oder nicht.
<dein Beispiel>
select
-- lange "Select-Argumentenliste"
join
-- lange "Join-Datentabellenliste"
where
(x = y)
select
-- lange mit der o.g. Abfrage identische "Select-Argumentenliste"
join
-- lange mit der o.g. Abfrage identische "Join-Datentabellenliste"
where
(y = z)
-- u.s.w
</ende>
nach welchen Kriterien entscheidest Du welche Abfrage relevant ist?
ciao
romy
Hi,
<mein Beispiel>
if (@param = 'x=y')
begin
select
-- lange "Select-Argumentenliste"
join
-- lange "Join-Datentabellenliste"
where
(x = y)
end
else if (@param = 'y=z')
begin
select
-- lange mit der o.g. Abfrage identische "Select-Argumentenliste"
join
-- lange mit der o.g. Abfrage identische "Join-Datentabellenliste"
where
(y = z)
end
-- u.s.w
</ende>
Gruss,
Lude
Hi Lude,
<dein Beispiel>
if (@param = 'x=y')
begin
select
-- lange "Select-Argumentenliste"
join
-- lange "Join-Datentabellenliste"
where
(x = y)
end
else if (@param = 'y=z')
begin
select
-- lange mit der o.g. Abfrage identische "Select-Argumentenliste"
join
-- lange mit der o.g. Abfrage identische "Join-Datentabellenliste"
where
(y = z)
end
-- u.s.w
</ende>
Auch auf die Gefahr hin, dich falsch verstanden zu haben, antworte ich bescheidenerweise. ;)
Irgendwie sieht mir das nach einer Stringverknüpfung aus, wie auch immer das in Perl geht.
select
-- lange "Select-Argumentenliste"
join
-- lange "Join-Datentabellenliste"
where
stringvernüpfung @param
Warum sollte die Datenbank rausfinden können, welchen Parameter Du übergibst bzw. erwählst bzw. festlegst?
ciao
romy
Hi,
Irgendwie sieht mir das nach einer Stringverknüpfung aus, wie auch immer das in Perl geht.
also, ich habe zum Beispiel sowas (bitte auf die ---MARKE--- schaun)
CREATE
procedure
BIZ_DATENZUGRIFFE
@Session_GUID uniqueidentifier,
@Sortierung nvarchar (32)
/*
Gibt eine Liste der Datenzugriffe zurueck, wobei die Sortierungen 'alphabetisch', 'nach_Laufzeit' und
'nach_DS-Laufzeit' unterstuetzt werden
--
Autor: x
erstellt am: 17.02.2003
letzte Aenderung: 12.09.2003
--
24.02.2003 Pruefung auf 'Benutzer_GUID' und 'Recht_Name', und Logging erfolgt nun ueber
'SET_DATENZUGRIFF'
11.03.2003 Rechteabfrage auf "IsAdmin/IsUser" umgestellt
23.07.2003 Datenzugriffslogging nun mit 'SET_DATENZUGRIFF_START' und 'SET_DATENZUGRIFF_END'
09.09.2003 drei Filteroptionen implementiert
*/
as
begin
--
declare
@Benutzer_GUID uniqueidentifier,
@Recht_Name nvarchar (16),
@Datenzugriff_GUID uniqueidentifier
exec
SET_DATENZUGRIFF_START
@Session_GUID = @Session_GUID,
@Benutzer_GUID = @Benutzer_GUID output,
@Recht_Name = @Recht_Name output,
@Datenzugriff_SP = 'BIZ_DATENZUGRIFFE',
@Datenzugriff_GUID = @Datenzugriff_GUID output
--
if (dbo.IsAdmin(@Recht_Name) = 0)
begin
--
select
*
from
(
select
'benutzerspezifisch' as Zugriff,
Datenzugriff_SP,
count(*) as Anzahl,
min(Datenzugriff_Creation_Date) as Zuerst,
max(Datenzugriff_Creation_Date) as Zuletzt,
sum(datediff(millisecond,Datenzugriff_Creation_Date,Datenzugriff_Executed_Date)) as Laufzeit,
sum(datediff(millisecond,Datenzugriff_Creation_Date,Datenzugriff_Executed_Date)) / count(*) as [DS-Laufzeit]
from
DATENZUGRIFFE
where
(Datenzugriff_Benutzer_GUID = @Benutzer_GUID)
group by
Datenzugriff_SP
union
select
'total' as Zugriff,
Datenzugriff_SP,
count(*) as Anzahl,
min(Datenzugriff_Creation_Date) as Zuerst,
max(Datenzugriff_Creation_Date) as Zuletzt,
sum(datediff(millisecond,Datenzugriff_Creation_Date,Datenzugriff_Executed_Date)) as Laufzeit,
sum(datediff(millisecond,Datenzugriff_Creation_Date,Datenzugriff_Executed_Date)) / count(*) as [DS-Laufzeit]
from
DATENZUGRIFFE
group by
Datenzugriff_SP
) [Dummy]
order by
--
-- ---MARKE--- HIER SCHAUEN BITTE:
--
case @Sortierung
when 'alphabetisch' then Datenzugriff_SP
when 'nach_Laufzeit' then cast(2000000000 - cast(Laufzeit as int) as nvarchar)
when 'nach_DS-Laufzeit' then cast(2000000000 - cast([DS-Laufzeit] as int) as nvarchar)
end
end
else if (dbo.IsUser(@Recht_Name) = 0)
begin
--
select
*
from
(
select
'benutzerspezifisch' as Zugriff,
Datenzugriff_SP,
count(*) as Anzahl,
min(Datenzugriff_Creation_Date) as Zuerst,
max(Datenzugriff_Creation_Date) as Zuletzt,
sum(datediff(millisecond,Datenzugriff_Creation_Date,Datenzugriff_Executed_Date)) as Laufzeit,
sum(datediff(millisecond,Datenzugriff_Creation_Date,Datenzugriff_Executed_Date)) / count(*) as [DS-Laufzeit]
from
DATENZUGRIFFE
where
(Datenzugriff_Benutzer_GUID = @Benutzer_GUID)
group by
Datenzugriff_SP
) [Dummy]
order by
case @Sortierung
when 'alphabetisch' then Datenzugriff_SP
when 'nach_Laufzeit' then cast(2000000000 - cast(Laufzeit as int) as nvarchar)
when 'nach_DS-Laufzeit' then cast(2000000000 - cast([DS-Laufzeit] as int) as nvarchar)
end
end
--
exec
SET_DATENZUGRIFF_END
@Datenzugriff_GUID = @Datenzugriff_GUID
--
end
GO
Und mit dem "CASE-Krempel" bin ich ungluecklich. Vorher hatte ich aber 3 Queries mit identischer Datensatzmenge. Koennte noch zig weitere Beispiele geben. :~)
Gruss,
Lude
Hi ,
order by
case @Sortierung
when 'alphabetisch' then Datenzugriff_SP
when 'nach_Laufzeit' then cast(2000000000 - cast(Laufzeit as int) as nvarchar)
when 'nach_DS-Laufzeit' then cast(2000000000 - cast([DS-Laufzeit] as int) as nvarchar)
Puh, was passt Dir eigentlich nicht an der Case-Umsetzung?
Letztendlich musst Du so oder so das Ganze Abfragen ob per SQL oder per Script ist ja letztendlich egal, obwohl ich glaube, dass Script performanter ist (hängt glaube ich von der Schnelligkeit des jeweiligen Servers ab)
In @Sortierung steht jetzt ja aphabetisch drin, warum ist der Inhalt dieser Variable nicht gleich 'Datenzugriff_SP' ? (Für die anderen Variablen genauso) Und in dem Statement sortierst Du praktisch nach @Sortierung.
Oder Du fragst es vorher in einem If-Else-Statement ab und generierst DIe eine Variable Sortierung, die dann den gewünschten Wert enthält.
order by @Sortierung
Mehr fällt mir jetzt auch nicht ein.
ciao
romy
Hi, romy,
Hi ,
order by
case @Sortierung
when 'alphabetisch' then Datenzugriff_SP
when 'nach_Laufzeit' then cast(2000000000 - cast(Laufzeit as int) as nvarchar)
when 'nach_DS-Laufzeit' then cast(2000000000 - cast([DS-Laufzeit] as int) as nvarchar)
Puh, was passt Dir eigentlich nicht an der Case-Umsetzung?
so ziemlich alles. Der Wert '2000000000', der soz. den maximal moeglichen integer-Wert definiert und der notwendig ist um eine absteigende Sortierung zu erreichen. Dann die Typumwandlungen. Dann, dass es mir nicht ohne weitere "Tricks" moeglich ist mehrere Argumente an die 'order by'-Klausel zu uebergeben.
Letztendlich musst Du so oder so das Ganze Abfragen ob per SQL oder per Script ist ja letztendlich egal, obwohl ich glaube, dass Script performanter ist (hängt glaube ich von der Schnelligkeit des jeweiligen Servers ab)
"Script" heisst umgebende Programmlogik und kann deshalb nicht performanter sein. Ausserdem habe ich die saubere Trennung zwischen Datenzugriff und "Programmlogik" gerne.
In @Sortierung steht jetzt ja aphabetisch drin, warum ist der Inhalt dieser Variable nicht gleich 'Datenzugriff_SP' ? (Für die anderen Variablen genauso) Und in dem Statement sortierst Du praktisch nach @Sortierung.
Wenn ich mit vorkompilierten Prozeduren arbeite, kann ich in die 'order by'-Klausel oder in die 'where'-Klausel keine Variablen setzen.
Oder Du fragst es vorher in einem If-Else-Statement ab und generierst DIe eine Variable Sortierung, die dann den gewünschten Wert enthält.
s.o.
Beschaeftige Dich doch mal mit serverseitig gespeicherten Datenzugriffsprozeduren. Ist ganz interessant. Allerdings kann das MySQL wohl nicht!?
Gruss,
Lude