2017-03-12 4 views
0

Ich habe eine Tabelle TableA wie in MS-Sql
Alternative zu 'Außer' in SQL mit Leistung

TrId Status 
2345 3 
    567 3 
    567 0 
2345 0 
    99 3 
    778 0 

Szenario ist wenige TrIds Status als 3 haben sowie 0, einige haben 3 nur einige 0 nur. Ich brauche TrIds mit Status finden nur 3
Einer der Wege, zu tun ist:

Select TrnId From TableA Where flgStatus = 3 
EXCEPT 
Select TrnId From Tablea Where flgStatus = 0 

Es gibt über 100 Millionen Platten und ich habe nicht genug Zeitfenster für die Ausnahme, keine Alternative für diese wäre dankbar.

+1

Welcher SQL-Geschmack? (PostgreSQL, MySQL, SQL Server, ...?) – Ryan

+0

wahrscheinlich Postgrad –

+0

@Ryan: Ups! es ist Frau-skl. Es ist jetzt hinzugefügt – EetSandhu

Antwort

1

Ist die Kombination (TrnId,flgStatus) einzigartig?

Dann könnte schalten Sie EXCEPT ALL, ähnlich wie UNION ALL, die als UNION effizienter sein könnte, weil es die DISTINCT-Operation vermeidet.

Eine andere Lösung, die die Basistabelle nur einmal greift:

Select TrnId 
From TableA Where flgStatus in (0,3) 
group by TrnId 
having MIN(flgStatus) = 3 
+0

Das bringt nicht das gewünschte Ergebnis. Wenn Sie es in "MIN (flgStatus) = 3" ändern, tut es das auch. – Igor

+1

@Igor: Natürlich, danke, dass Sie darauf hingewiesen haben. – dnoeth

1

EXCEPT oder MINUS ist das Richtige hier. Auf einem sehr großen Tisch ist es jedoch nicht optimal.

wäre eine Alternative dies besser

SELECT * 
FROM TableA 
WHERE flgStatus = 3 
AND TrnId NOT IN 
(SELECT TrnId From TableA Where flgStatus = 0) 

Oder auch, LEFT JOIN und IS NULL mit dem NOT zu vermeiden, die ein perf Killer:

SELECT * 
FROM TableA T3 
LEFT JOIN TableA T0 ON T3.TrnId = T0.TrnId AND T0.flgStatus = 0 
WHERE T3.flgStatus = 3 
    AND T0.TrnId IS NULL 

Edit: NOT EXISTS Lösung von Igor ist auch ein Guter Ansatz

+0

Ich werde die Leistung dafür am Dienstag überprüfen und lassen Sie wissen, wenn ich muss Schlag den grünen Scheck! :) – EetSandhu

3

Sie können NOT EXISTS

verwenden
SELECT * 
FROM TableA a 
WHERE flgStatus = 3 
AND NOT EXISTS 
(SELECT TrnId From TableA b Where flgStatus = 0 AND a.TrnId = b.TrnId) 

Dies hat im Allgemeinen eine bessere Leistung als NOT IN. Eine gute Alternative wäre ein Join, siehe @ThomasG 'Antwort.

+1

Ich bin mir ziemlich sicher, dass 'JOIN' nicht funktionieren wird. – Ryan

1

ich ein einfaches group by verwenden würde:

select trnid 
from tablea 
group by trnid 
having min(status) = max(status) and min(status) = 3; 

Ob dies schneller oder nicht, hängt von mehreren Dingen. . . vor allem, ob du Duplikate entfernen möchtest oder welche Indizes du für die Daten hast. NOT EXISTS ist wahrscheinlich schneller, wenn Duplikate nicht wichtig sind, aber die doppelte Eliminierung erfordert Arbeit.

+0

Nun, dieser braucht fast die doppelte Zeit von @dnoeths Antwort. – EetSandhu

+0

@EetSandhu. . . Sie müssen dann andere Status in Ihrer Tabelle haben. –

+0

Ja. 0,1,3 alle alle Statusarten. Ich habe oben nur aus Gründen aller gesagt. Ansonsten funktioniert es gut. – EetSandhu

0

Für große Datenmengen wie das Ihre, die folgenden Abfrage verwendet, kann das gewünschte Ergebnis mit hinreichender Leistung geben -

SELECT ta1.TrId AS TrId 
FROM dbo.TableA AS ta1 
LEFT JOIN dbo.TableA AS ta2 ON (ta2.TrId = ta1.TrId AND ta2.[Status] != 3) 
WHERE ta2.TrId IS NULL; 

Zuerst wird die Selbstverknüpfung wird eine Tabelle erstellt, indem alle Status Anordnung (3 oder 0, 1 usw.) in derselben Zeile. Der Filter

ta2.[Status] != 3 

in der Klausel legt für die ta2.TrId NULL verbinden (oder TA2. *), Wenn der Status 3 ist.

+------+--------+------+--------+ 
| TrId | Status | TrId | Status | 
+------+--------+------+--------+ 
| 2345 |  3 | 2345 | 0  | 
| 567 |  3 | 567 | 0  | 
| 567 |  0 | 567 | 0  | 
| 2345 |  0 | 2345 | 0  | 
| 99 |  3 | NULL | NULL | 
| 778 |  0 | 778 | 0  | 
+------+--------+------+--------+ 

Dann wird der folgende Filter verwendet, um Zeilen auszuwählen, wo der NULL auftritt.

WHERE ta2.TrId IS NULL 

Da es selbst LEFT JOIN ist, hat die linke Tabelle alle Zeilen aber NULL für rechten Tabellenwerte, bei denen die Kriterien kommen nicht erfüllt.

+0

Ich überprüfe die Leistung von diesem Freitag und lass es dich wissen. wenn das am besten für mich oder die akzeptierte Antwort von @dnoeth funktioniert. – EetSandhu

+0

Ich wusste vorher nicht, dass Sie einen anderen Status als 0 und 3 haben. Also habe ich meine Antwort aktualisiert und den Filter der Join-Klausel ein wenig geändert. Ich bin auch begierig darauf, den Vergleich zwischen der Gruppe und Versionen dieser Lösungen für große Datenmengen zu sehen. – Shiblu