AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken in-Klausel in großen Tabellen

in-Klausel in großen Tabellen

Ein Thema von Ykcim · begonnen am 8. Feb 2019 · letzter Beitrag vom 11. Feb 2019
Antwort Antwort
Seite 4 von 5   « Erste     234 5   
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.733 Beiträge
 
Delphi 6 Enterprise
 
#31

AW: in-Klausel in großen Tabellen

  Alt 11. Feb 2019, 07:51
Aber muss nicht bei der Distinct + Join Variante der Distinct nur 1x gemacht werden, während beid er exists Variante für jeden Datensatz ein Subselect gemacht werden muss?
Ralph
  Mit Zitat antworten Zitat
Benutzerbild von ConnorMcLeod
ConnorMcLeod

Registriert seit: 13. Okt 2010
Ort: Bayern
490 Beiträge
 
Delphi 10.4 Sydney
 
#32

AW: in-Klausel in großen Tabellen

  Alt 11. Feb 2019, 08:36
Ich mag auch mal

Delphi-Quellcode:
select
    A.AuftragsNr
  , A.Arbeitsgang
from
  Auftrag A
join
  (
  select
    *
  from
    (
    select
        Sub.AuftragsNr
      , count(Sub.Arbeitsgang) Anzahl
    from
      Auftrag Sub
    where
      (Sub.FertigDatum between 'ANFANGand 'ENDE')
    group by
      Sub.AuftragsNr
    ) AufAnz
  where
    (0 < AufAnz.Anzahl)
  ) OnlyNotZero
on
  (OnlyNotZero.AuftragsNr = A.AuftragsNr)
Nr.1 Delphi-Tool: [F7]
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#33

AW: in-Klausel in großen Tabellen

  Alt 11. Feb 2019, 08:56
Aber muss nicht bei der Distinct + Join Variante der Distinct nur 1x gemacht werden, während beid er exists Variante für jeden Datensatz ein Subselect gemacht werden muss?
Für das exists spricht, das es der menschlichen Denke engegenkommt. Ich habe aber die Erfahrung gemacht, das ein Join mit einem check auf NULL wesentlich schneller ist.

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.415 Beiträge
 
Delphi 7 Professional
 
#34

AW: in-Klausel in großen Tabellen

  Alt 11. Feb 2019, 09:13
Aber muss nicht bei der Distinct + Join Variante der Distinct nur 1x gemacht werden, während beid er exists Variante für jeden Datensatz ein Subselect gemacht werden muss?
Warum sollte das so sein?

Dort ist eine recht gute Erklärung zu finden: https://stackoverflow.com/questions/...-exists-clause

Zitat von JNK:
EXISTS is used to return a boolean value, JOIN returns a whole other table

EXISTS is only used to test if a subquery returns results, and short circuits as soon as it does. JOIN is used to extend a result set by combining it with additional fields from another table to which there is a relation.

In your example, the queries are symantically equivalent.

In general, use EXISTS when:

You don't need to return data from the related table
You have dupes in the related table (JOIN can cause duplicate rows if values are repeated)
You want to check existence (use instead of LEFT OUTER JOIN...NULL condition)

If you have proper indexes, most of the time the EXISTS will perform identically to the JOIN. The exception is on very complicated subqueries, where it is normally quicker to use EXISTS.
Beide Varianten prüfen, ob es zu der Bedingung ein "Gegenstück" gibt. Während Exists nur sagt: "Ja gibt es" bzw. "Nein, gibt es nicht", liefert Join das Gegenstück. Bei großen Datenmengen kann das schon einen großen Unterschied bezüglich des Speicherbedarfes geben.
Unter Oracle war es zu Zeiten, als ich mich damit noch beruflich befasste, deutlich schneller, mit Exists zu arbeiten. Spätestens, wenn die Datenbank den temporary tablespace nutzen musste, konnte man da Unterschiede bemerken, weil irgendwann die Auslagerung des Speichers auf die Festplatte(n) sich im Laufzeitverhalten deutlich bemerkbar machte.

Hier im konkreten Fall müssen wir nur wissen, ob es zu 'nem Auftrag mindestens einen Satz im gewünschten Jahr gibt, um dann alle Datensätze zu der Auftragsnummer auszugeben.

Mit Exists erhalten wir nur ein Ja oder ein Nein, bei 'nem Join erhalten wir alle Datensätze aus dem gewünschten Jahr. Die werden dann (erstmal) mit allen Datensätzen der Auftragsnummer verbunden. Es kann also (auf Auftragsnummerebene) einen CROSS JOIN geben. (DeddyHs diesbezügliche Anmerkung ist daher angebracht.) Bei einem Join muss man also auch noch sicherstellen, dass keine (partiziellen) Dubletten entstehen. Das ist aufwändiger, als eine "simple" Existenzprüfung. Daher ist (meiner Meinung nach) im vorliegenden Fall Exists vorzuziehen.
  Mit Zitat antworten Zitat
peterbelow

Registriert seit: 12. Jan 2019
Ort: Hessen
672 Beiträge
 
Delphi 11 Alexandria
 
#35

AW: in-Klausel in großen Tabellen

  Alt 11. Feb 2019, 10:14
Zitat:
select * from tabelle
where AuftragNr in (
select AuftragNr from Tabelle where Year(FertigDatum) = 2018 group by AuftragNr)
Wozu das group by in der inneren query? Eventuell funktioniert das hier besser:

Code:
select distinct <feldliste> from tabelle
where exists (
select AuftragNr from Tabelle where Year(FertigDatum) = 2018)
order by auftragnr, arbeitsgang
Ich hatte allerdings auch schon Fälle, wo es nicht anders ging als ein Zwischenergebnis in einer temporären Tabelle zu speichern. In deinem Fall würde man da
das Resultat von

Code:
select distinct AuftragNr from Tabelle where Year(FertigDatum) = 2018)
ablegen. Diese Query gibt halt deutlich weniger Zeilen zurück als ohne "distinct", ist aber aufwendiger in der Verarbeitung.
Peter Below
  Mit Zitat antworten Zitat
freejay

Registriert seit: 26. Mai 2004
Ort: Nürnberg
269 Beiträge
 
Delphi 11 Alexandria
 
#36

AW: in-Klausel in großen Tabellen

  Alt 11. Feb 2019, 12:56
Also ich würde folgendes tun:

1. Ein Feld "Jahr" einführen und entsprechend füllen
2. Einen Index für das Feld "Jahr" anlegen
3. Anschließend folgende Abfrage ausprobieren:

Code:
SELECT * FROM tabelle a
INNER JOIN (
  SELECT DISTINCT AuftragNr FROM Tabelle where Jahr = 2018) i ON a.AuftragNr = i.AuftragNr
ORDER BY auftragnr, arbeitsgang
4. Falls das nicht performant ist, dann das Ergebnis der inneren Abfrage vorher in einer (temporären) Tabelle zwischenspeichern (in dieser Tabelle den Index auf AuftragNr nicht vergessen!) und dann die obengenannte Abfrage auf die temporäre Tabelle machen. Das würde dann ungefähr so aussehen:

Code:
CREATE TEMPORARY TABLE `temptable` (
  `AuftragNr` int(11),
  PRIMARY KEY (`AuftragNr`)
) ENGINE=InnoDB;
                 
INSERT INTO `temptable` 
  SELECT DISTINCT AuftragNr FROM Tabelle where Jahr = 2018;

SELECT * FROM `tabelle` a
INNER JOIN `temptable` i ON a.AuftragNr = i.AuftragNr
ORDER BY AuftragNr, arbeitsgang;

DROP TEMPORARY TABLE `temptable`;
Wenn diese Statements zusammen nicht innerhalb eines Fingeschnippsens durch sind, fresse ich einen Besen...

PS1: Ich habe nicht alle vorherigen Antworten komplett durchgelesen, vielleicht wiederhole ich auch nur bereits Gesagtes.
PS2: Ich habe die Statements nicht ausprobiert.
[Delphi 11.3.1 Enterprise; Win10/11; MySQL; VCL]
  Mit Zitat antworten Zitat
freejay

Registriert seit: 26. Mai 2004
Ort: Nürnberg
269 Beiträge
 
Delphi 11 Alexandria
 
#37

AW: in-Klausel in großen Tabellen

  Alt 11. Feb 2019, 13:16
PS: Ich gehe doch mal davon aus, dass der Themenersteller in seiner Tabelle auf jeden Fall einen Index auf `AuftragsNr` hat...
[Delphi 11.3.1 Enterprise; Win10/11; MySQL; VCL]
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.415 Beiträge
 
Delphi 7 Professional
 
#38

AW: in-Klausel in großen Tabellen

  Alt 11. Feb 2019, 13:39
Die Auftragsnummer wird über concat(waaunr,'-', waaupo) gebildet. Sie ist ein Konstrukt mehrerer Werte, die zusammen zu einem gewünschten Jahr existieren müssen. Ist diese Existenz gegeben, müssen alle Sätze, die über dieses Konstrukt verfügen, von der Datenbank herausgesucht werden.
  Mit Zitat antworten Zitat
freejay

Registriert seit: 26. Mai 2004
Ort: Nürnberg
269 Beiträge
 
Delphi 11 Alexandria
 
#39

AW: in-Klausel in großen Tabellen

  Alt 11. Feb 2019, 13:45
Die Auftragsnummer wird über concat(waaunr,'-', waaupo) gebildet. Sie ist ein Konstrukt mehrerer Werte, die zusammen zu einem gewünschten Jahr existieren müssen. Ist diese Existenz gegeben, müssen alle Sätze, die über dieses Konstrukt verfügen, von der Datenbank herausgesucht werden.
Ok, das habe ich übersehen. Das ist ja aber für die Performance ganz schlecht. Ich würde daher dringend empfehlen, diesen Wert als echtes Tabellenfeld einzuführen. Ja, das ist irgendwie redundant, aber manchmal, wenn's um die Performance geht ist das die einzige wirklich gut funktionierende Lösung.
[Delphi 11.3.1 Enterprise; Win10/11; MySQL; VCL]
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.415 Beiträge
 
Delphi 7 Professional
 
#40

AW: in-Klausel in großen Tabellen

  Alt 11. Feb 2019, 14:06
Das ist nur dann nicht performant, wenn man für die Abfrage zuerst die beiden Felder zusammenfasst und diese Zusammenfassung für die Wherebedingung nutzt. Da man die Wherebedingung aber über die beiden Felder separat machen kann, sollte das durchaus schnell mit einer Exists-Prüfung im SQL zu realisieren sein. Klar, der Index muss auf diese Abfrage optimiert sein, dass sollte aber mit 'ner modernen Datenbank im Rahmen des Möglichen sein.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:30 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz