Softpicks.Net  Deutsch Foren-Übersicht Softpicks.Net Deutsch
Software Forum Deutsch
 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen   RegistrierenRegistrieren 
 ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Effiziente Fallunterscheidung in Stored Procedure

 
Neues Thema eröffnen   Neue Antwort erstellen    Softpicks.Net Deutsch Foren-Übersicht -> SQL Server
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Stefan Falz



Anmeldedatum: 01.01.1970
Beiträge: 72

BeitragVerfasst am: Di Dez 19, 2006 9:28 pm    Titel: Effiziente Fallunterscheidung in Stored Procedure Antworten mit Zitat



Hallo Mark,

"Mark Schneider" schrieb:

> "Ja" oder "Nein" zurückzugeben, je nachdem, ob die jeweilige Artikel-ID auch
> in Details vertreten ist.

Da würde ich einfach abfragen, ob die Anzahl der in der Detailtabelle zum Artikel
zugehörigen Datensätze > 0 ist und wenn ja, den entsprechenden String zurückgeben.

> nun benötige ich ein Statement, dass mir in etwa folgendes zurückgibt
> alle Artikel aus A mit einem zusätzlichen Hinweis, ob sie in B vorkommen
> ID / Bezeichnung / ... / DetailsVorhanden
> 1 / Artikel A / ... / NEIN
> 2 / Artikel B / ... / JA
> 3 / Artikel C / ... / NEIN

SELECT Spalte1,
CASE ( SELECT TOP 1 1 FROM <DetailTabelle> D WHERE M.<Id> = D.<ForeignKey> )
WHEN 1 THEN 'Ja'
ELSE 'Nein'
END
AS Spalte2
FROM <MasterTabelle> M

> Alles klar?

Nö :)

Ich hab das da oben nur schnell zusammengeschrieben. Wenn ich mir das morgen
wieder ansehe, hau ich mir das bestimmt selbst um die Ohren (wenns die SQL
Spezialisten nicht schon vorher machen). Aber Hey, es funktioniert Smile)

--
Tschau, Stefan
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspforum.de/ - Antworten zu ASP/ASP.NET

.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Stefan Falz



Anmeldedatum: 01.01.1970
Beiträge: 72

BeitragVerfasst am: Di Dez 19, 2006 11:13 pm    Titel: Effiziente Fallunterscheidung in Stored Procedure Antworten mit Zitat



Hallo Hannes,

"Hannes Brunner" schrieb:

> Ich will mich jetzt nicht als Spezialist bezeichnen, aber ich hau dir
> das trotzdem um die Ohren (SCNR).

:))

> Wenn man wissen will, ob Datensätze existieren, nimmt man am besten
> EXISTS(). Dann hat der Server alle Freiheiten die Strategie auszuwählen
> die ihm am besten in den Kram passt. Also:
>
> SELECT Spalte1,
> CASE WHEN EXISTS(SELECT 'bla' FROM D WHERE M.<Id> = D.<ForeignKey>)

Aargh Smile) Das wollt ich ja eigentlich machen aber in einem Anfall geistiger
Umnachtung hab ich das Statement nicht zum laufen bekommen Smile) Wird wohl an
der Uhrzeit liegen. Alte Männer gehören da schon längst ins Bett :)

--
Tschau, Stefan
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspforum.de/ - Antworten zu ASP/ASP.NET

.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Stefan Falz



Anmeldedatum: 01.01.1970
Beiträge: 72

BeitragVerfasst am: Mi Dez 20, 2006 8:46 am    Titel: Effiziente Fallunterscheidung in Stored Procedure Antworten mit Zitat



Hallo Henry,

"Henry Habermacher [MVP Access]" schrieb:

> Ich bin nicht sicher, ob da das erste Wort im Subject auch wirklich erfüllt
> ist.

Ich mir auch (noch) nicht. Aber ich hatte gestern auch über eine Lösung ähnlich
deiner nachgedacht.

> SELECT DISTINCT
> Artikel.ID,
> Artikel.Bezeichnung,
> CASE WHEN Details.ID IS NULL
> THEN N'Nein'
> ELSE N'Ja'
> END AS DetailsVorhanden
> FROM Artikel LEFT OUTER JOIN
> Details ON Artikel.ID = Details.ID

Wenn ich mir den Abfrageplan beider Varianten anschaue, seh ich bis auf ein
autom. eingefügtes SORT und den damit verbundenen Kosten bei meiner (Hannes)
Variante keinen großen Unterschied. Anstelle von TOP 1 ... hab ich hier
natürlich EXISTS genommen (siehe Posting von gestern abend).

> Wenn Primary und Foreign Key sauber gesetzt sind, dann sollte dieses
> Statement einiges "effizienter" sein, als ein Sub-Select.

Wie genau SQL Server da optimiert, wenn DISTINCT verwendet wird, weiß
ich natürlich nicht. Ich muss das nachher mal mit ein paar mehr Daten-
sätzen austesten. Interessiert mich jetzt schon Smile)

--
Tschau, Stefan
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspforum.de/ - Antworten zu ASP/ASP.NET

.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Mark Schneider



Anmeldedatum: 01.01.1970
Beiträge: 4

BeitragVerfasst am: Mi Dez 20, 2006 9:34 am    Titel: Effiziente Fallunterscheidung in Stored Procedure Antworten mit Zitat



Auf genau so eine Diskussion hatte ich gehofft. Danke an Euch 3!
Meine temporäre Lösung war ähnlich der von Stefan,
jedoch (unsaubererweise) nicht mal mit top 1. Der left
join ist eigentlich sehr naheliegend, habe mich jetzt dafür
entschieden (danke, Henry!), zumal das auch in komplexeren
Fällen sehr kompakt und lesbar bleibt.

Liebe Grüße und schöne Weihnachtstage
Mark


.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Stefan Falz



Anmeldedatum: 01.01.1970
Beiträge: 72

BeitragVerfasst am: Mi Dez 20, 2006 10:20 am    Titel: Effiziente Fallunterscheidung in Stored Procedure Antworten mit Zitat



Hallo Christa,

"Christa Kurschat" schrieb:

> Case ist i.d.R. nie effizient. ;-)

Wohl wahr, aber das haben wir ja beide drin Smile) Was gäbe es denn
für die Anforderung des OP noch an Lösungen? (Welche, die ohne
Case auskommen)

> Wenn Du "where exists" verwendest, mach das u.U. keinen Unterschied, vor
> allem nicht, wenn es sich um nicht viele DS handelt.
> Anders sieht es aus, wenn Du "where not exists" nimmst, da habe ich schon
> Fälle gehabt, wo die join-Löung sehr viel schneller ist.

Naja, wenn ich 1000 Zuordnungen und 10000000 "Nicht Zuordnungen" habe, wäre
man ja schlecht beraten, "not exists" zu nehmen :)

> Ich würde auch eher Henrys Lösung verwenden.

Ich (noch) nicht Smile Erst will ich meine Tests machen. Dann schau ich weiter.

> Auch distinct nur verwenden, wenn unbedingt nötig.

Ist hierfür ja aber notwendig, da ansonsten alle DS aus der Mastertabelle
zurückkommen. Group By wäre hier sicher auch nicht der Hammer :)

> Aber teste ruhig mal die Laufzeiten und poste sie hier.
> Interessiert mich auch.
> Aber nimm genug DS. Bei 1000 wirst Du keinen Unterschied feststellen, bei 1
> Mio mag das anders aussehen.

Klar. Da kommt schon etwas mehr rein (bzw. such ich mir grad ne Datenbank
raus, die genug Daten hat)

--
Tschau, Stefan
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspforum.de/ - Antworten zu ASP/ASP.NET

.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Stefan Falz



Anmeldedatum: 01.01.1970
Beiträge: 72

BeitragVerfasst am: Mi Dez 20, 2006 11:25 am    Titel: Effiziente Fallunterscheidung in Stored Procedure Antworten mit Zitat



Hallo Elmar,

"Elmar Boye" schrieb:

> Prozentuale Verteilung im Ausführungsplan hier: 10%, 79%, 5%, 5%
> Wo man sehen kann das DISTINCT nicht unbedingt keine gute Idee ist,
> eine Abneigung gegen CASE nicht unbedingt angebracht
> und das TOP einen fast identischen Plan wie GROUP BY erzeugt.

Und welches Ergebnis ist nun subjektiv für dich das "beste"? Das konnte
ich aus dem Posting leider nicht so ganz rauslesen Smile)

--
Tschau, Stefan
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspforum.de/ - Antworten zu ASP/ASP.NET

.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Christa Kurschat



Anmeldedatum: 01.01.1970
Beiträge: 1036

BeitragVerfasst am: Mi Dez 20, 2006 11:33 am    Titel: Effiziente Fallunterscheidung in Stored Procedure Antworten mit Zitat



Hallo Stefan,

Stefan Falz <ms.news [at] asp-solutions.de> schrieb:

> Hallo Christa,
>
> "Christa Kurschat" schrieb:
>
>> Case ist i.d.R. nie effizient. Wink
>
> Wohl wahr, aber das haben wir ja beide drin Smile) Was gäbe es
> denn für die Anforderung des OP noch an Lösungen? (Welche, die
> ohne Case auskommen)
>

Manchmal muß man eben Dinge verwenden, die nicht effektiv sind Wink
In dem Fall gibt es keine andere Lösung.

Gruß
Christa
--
Access-FAQ: http://www.donkarl.com
SQL-Server-FAQ: www.sqlfaq.de
InsideSql: www.insidesql.de
Suchen in den Newsgroups:
http://groups.google.de/advanced_group_search?hl=de&lr=&ie=UTF-8

.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Christa Kurschat



Anmeldedatum: 01.01.1970
Beiträge: 1036

BeitragVerfasst am: Mi Dez 20, 2006 1:02 pm    Titel: Effiziente Fallunterscheidung in Stored Procedure Antworten mit Zitat



Hallo Henry,

Henry Habermacher [MVP Access] <DontSpamHenry [at] psp-online.com> schrieb:

> Hallo Elmar
>
> quoting Elmar Boye:
>> Wo man sehen kann das DISTINCT nicht unbedingt keine gute
>> Idee ist,
>
> wolltest Du eine, statt keine schreiben? Gemäss der
> prozentualen Verteilung wäre ja Distinct krass langsamer. Wäre
> in diesem Fall Group By einem Distinct in der Regel
> vorzuziehen?

Ich glaube nicht, daß schneller oder effektiver ist.
Ich verwend nach Möglichkeit distinct statt groub by und meine, daß es etwas
besser ausgeführt wird.
Richtig getestet habe ich es allerdings noch nicht.

Gruß
Christa
--
Access-FAQ: http://www.donkarl.com
SQL-Server-FAQ: www.sqlfaq.de
InsideSql: www.insidesql.de
Suchen in den Newsgroups:
http://groups.google.de/advanced_group_search?hl=de&lr=&ie=UTF-8

.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Georg Trapmal



Anmeldedatum: 01.01.1970
Beiträge: 36

BeitragVerfasst am: Mi Dez 20, 2006 2:33 pm    Titel: Effiziente Fallunterscheidung in Stored Procedure Antworten mit Zitat



Hallo zusammen

> Unten eine Zusammenfassung der bisherigen Varianten gegen die
> AdventureWorks (mit SalesOrderDetails, Products), die im Gegensatz
> zur Northwind ein paar Datenzeilen mehr enthält.
> Prozentuale Verteilung im Ausführungsplan hier: 10%, 79%, 5%, 5%
> Wo man sehen kann das DISTINCT nicht unbedingt keine gute Idee ist,
> eine Abneigung gegen CASE nicht unbedingt angebracht
> und das TOP einen fast identischen Plan wie GROUP BY erzeugt.
>

Hab auch noch einen Lösungsvorschlag, der auch maximal 5% Anteil aufweisen
sollte bei den bisherigen von Elmar zusammengetragenen Varianten. Wenn GROUP
BY innerhalb des LEFT JOIN benutzt wird, dann werden die Duplikate da
entfernt, wo sie anfallen. Man muss sich nachher nicht mehr um doppelte
Einträge bei der Haupttabelle kümmern und kann entsprechend alle notwendigen
Spalten aus der Haupttabelle aufnehmen, ohne dass diese nochmals in einen
GROUP BY aufgenommen werden müssen.


SELECT p.ProductID, p.Name,
CASE WHEN sod.[FirstProductID] IS NOT NULL
THEN N'Nein'
ELSE N'Ja'
END AS DetailsVorhanden
FROM Production.Product AS p
LEFT OUTER JOIN
(
SELECT sod.ProductID,
MIN(sod.ProductID) AS [FirstProductID]
FROM Sales.SalesOrderDetail AS sod
GROUP BY sod.ProductID
) AS sod
ON p.ProductID = sod.ProductID


Alternativ könnte natürlich noch das Datenbank-Design geändert werden, indem
man die Haupttabelle denormalisiert und ein Flag aufnimmt, ob bzw. wieviele
Datensätze in der anderen Tabelle vorhanden sind. Dies bringt
Synchronisationsaufwand und/oder (Dead)Lock-Gefahren mit sich, kann aber
vorteilhaft sein, wenn Performance bei der Abfrage eine grosse Rolle spielt,
da der JOIN dann entfällt.

Gruss
Georg


> --
>
> SELECT p.ProductID, p.Name,
> CASE WHEN EXISTS(SELECT *
> FROM Sales.SalesOrderDetail AS sod
> WHERE p.ProductID = sod.ProductID)
> THEN 'Ja'
> ELSE 'Nein'
> END AS DetailsVorhanden
> FROM Production.Product AS p
> -- ORDER BY p.ProductID
> GO
>
> SELECT DISTINCT p.ProductID, p.Name,
> CASE WHEN sod.ProductID IS NULL
> THEN N'Nein'
> ELSE N'Ja'
> END AS DetailsVorhanden
> FROM Production.Product AS p
> LEFT OUTER JOIN Sales.SalesOrderDetail AS sod
> ON p.ProductID = sod.ProductID
> -- ORDER BY p.ProductID
> GO
>
> SELECT p.ProductID, p.Name,
> CASE (SELECT TOP (1) 1
> FROM Sales.SalesOrderDetail AS sod
> WHERE sod.ProductID = p.ProductID )
> WHEN 1 THEN 'Ja'
> ELSE 'Nein'
> END AS DetailsVorhanden
> FROM Production.Product AS p
> -- ORDER BY p.ProductID
> GO
>
> SELECT p.ProductID, p.Name,
> -- COALESCE (MIN(sod.ProductID), 0) AS KeineDetails
> -- oder wie oben
> CASE WHEN MIN(sod.ProductID) IS NULL
> THEN N'Nein'
> ELSE N'Ja'
> END AS DetailsVorhanden
> FROM Production.Product AS p
> LEFT OUTER JOIN Sales.SalesOrderDetail AS sod
> ON p.ProductID = sod.ProductID
> GROUP BY p.ProductID, p.Name
> -- ORDER BY p.ProductID
> GO
>
>
>


.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Elmar Boye



Anmeldedatum: 01.01.1970
Beiträge: 2462

BeitragVerfasst am: Mi Dez 20, 2006 4:04 pm    Titel: Effiziente Fallunterscheidung in Stored Procedure Antworten mit Zitat



Henry Habermacher [MVP Access] <DontSpamHenry [at] psp-online.com> schrieb ...
> Hallo Elmar
>
> quoting Elmar Boye:
>> Wo man sehen kann das DISTINCT nicht unbedingt keine gute Idee ist,
>
> wolltest Du eine, statt keine schreiben?

Wollte ich - und keine doppelte Verneinung Sad.

> Gemäss der prozentualen Verteilung wäre ja Distinct krass langsamer.

Was zu grossen Teilen an einem Hash Match für die Ausgabe liegt,
auf dem der Optimierer "besteht", auch wenn die Indexstruktur -
es gibt einen eindeutigen Index auf Product.Name anderes
ermöglichen würde (alle anderen Abfragen nutzen den).

> Wäre in diesem Fall Group By einem Distinct in der Regel vorzuziehen?

Das würde ich nicht generell empfehlen. Zum Problem kann es werden,
wenn mehr Spalten aus der Basistabelle (Product) benötigt werden,
da kriegt man womöglich eine grosse Arbeitskopie uam.

Die Varianten mit TOP oder auch EXISTS sind insofern universeller,
da sie leicher erweiterbar sind.

Gruss
Elmar

.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Elmar Boye



Anmeldedatum: 01.01.1970
Beiträge: 2462

BeitragVerfasst am: Mi Dez 20, 2006 4:24 pm    Titel: Effiziente Fallunterscheidung in Stored Procedure Antworten mit Zitat



Georg Trapmal <nospamplease [at] hotmail.com> schrieb ...
>> Unten eine Zusammenfassung der bisherigen Varianten gegen die
>> AdventureWorks (mit SalesOrderDetails, Products), die im Gegensatz
>> zur Northwind ein paar Datenzeilen mehr enthält.
>> Prozentuale Verteilung im Ausführungsplan hier: 10%, 79%, 5%, 5%
>
> Hab auch noch einen Lösungsvorschlag, der auch maximal 5% Anteil aufweisen
> sollte bei den bisherigen von Elmar zusammengetragenen Varianten.

Tut er: Es kommt der gleiche Abfrageplan wie bei der TOP Variante raus.

> Wenn
> GROUP BY innerhalb des LEFT JOIN benutzt wird, dann werden die Duplikate
> da entfernt, wo sie anfallen.

Wobei dabei anzumerken wäre, dass dies nur genau mit der Kombination
in der SELECT Liste passiert.

> LEFT OUTER JOIN
> (
> SELECT sod.ProductID,
> MIN(sod.ProductID) AS [FirstProductID]
> FROM Sales.SalesOrderDetail AS sod
> GROUP BY sod.ProductID
> ) AS sod

Die ja logisch identischen Varianten von wie nur
SELECT sod.ProductID mit GROUP BY
oder
SELECT MIN(sod.ProductID) AS [ProductID]
oder anstatt GROUP BY
SELECT DISTINCT ProductID
und selbst der Austausch von FirstProductID im CASE Teil
führenzu einem schlechteren Plan (da ein Stream Aggregate
eingebaut wird, anteilig ungefähr 20%).
Was IMO zeigt, dass der Optimierer längst nicht perfekt ist,
und manchmal seltsame Wege wandert, da er beim eher
"krummen" Wege das beste Ergebnis zeigt.

Gruss
Elmar

.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Elmar Boye



Anmeldedatum: 01.01.1970
Beiträge: 2462

BeitragVerfasst am: Mi Dez 20, 2006 4:29 pm    Titel: Effiziente Fallunterscheidung in Stored Procedure Antworten mit Zitat



Hallo Christa,

Christa Kurschat <christa_kurschat_nospam [at] web.de> schrieb ...
> Henry Habermacher [MVP Access] <DontSpamHenry [at] psp-online.com> schrieb:
>> quoting Elmar Boye:
>>> Wo man sehen kann das DISTINCT nicht unbedingt keine gute
>>> Idee ist,
>
> Ich glaube nicht, daß schneller oder effektiver ist.
> Ich verwend nach Möglichkeit distinct statt groub by
> und meine, daß es etwas besser ausgeführt wird.

In Anbetracht der Möglichkeiten sollte man sich aufs
"Meinen" weniger verlassen, sondern konkret messen.
Denn wie man sieht, kann selbst eine einfache Abfrage
heute auf unterschiedlichsten Wegen ausgedrückt werden -
extern vom Entwickler wie intern vom Optimierer.
Natürlich nur, wenns wirklich darauf ankommt!

Gruss
Elmar

.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Georg Trapmal



Anmeldedatum: 01.01.1970
Beiträge: 36

BeitragVerfasst am: Mi Dez 20, 2006 4:54 pm    Titel: Effiziente Fallunterscheidung in Stored Procedure Antworten mit Zitat



Hallo Elmar

>> LEFT OUTER JOIN
>> (
>> SELECT sod.ProductID,
>> MIN(sod.ProductID) AS [FirstProductID]
>> FROM Sales.SalesOrderDetail AS sod
>> GROUP BY sod.ProductID
>> ) AS sod
>
> Die ja logisch identischen Varianten von wie nur
> SELECT sod.ProductID mit GROUP BY
> oder
> SELECT MIN(sod.ProductID) AS [ProductID]
> oder anstatt GROUP BY
> SELECT DISTINCT ProductID
> und selbst der Austausch von FirstProductID im CASE Teil
> führenzu einem schlechteren Plan (da ein Stream Aggregate
> eingebaut wird, anteilig ungefähr 20%).
> Was IMO zeigt, dass der Optimierer längst nicht perfekt ist,
> und manchmal seltsame Wege wandert, da er beim eher
> "krummen" Wege das beste Ergebnis zeigt.

Mit den ersten beiden Varianten hatte ich auch gespielt und war verblüfft,
dass er dann zuerst mit der Tabelle SalesOrderDetail beginnt und ein Stream
Aggregate einbaut. Erklären kann ich mir das nicht wirklich; aber
interessieren würde mich schon, wieso er diese Vorgehensweise wählt.

Hast Du eine Erklärung dafür? Kann es sein, dass der Optimierer diesen Weg
wählt, weil die Spalte der JOIN-Bedingung auch im CASE benutzt wird, so dass
er dann "sowieso gerade" die ganze Tabelle SalesOrderDetail verarbeitet,
weil die ProductID aus SalesOrderDetail immer ausgewertet werden muss?

Aber mit einem der nächsten Service Pack macht dann der Optimierer sowieso
wieder was anderes... ;-)

Gruss
Georg


.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Softpicks.Net Deutsch Foren-Übersicht -> SQL Server Alle Zeiten sind GMT
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht teilnehmen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de