2016-03-20 8 views
2

Ich habe ein paar SQL-Tabellen, die mit FOS, Schlüsselwörter und PRef bezeichnet werden. Ihre Struktur und Beziehungen sind wie folgt:SQL-Zählung und mehrere Unterabfragen in großen Tabellen

+------------------+  +------------------+  +-----------------+ 
|  FOS  |  |  keywords  |  |  PRef  | 
+------------------+  +------------------+  +-----------------+ 
|fosID (PK)  |--+ |pkID (PK)   | +---|pID1 (PK)  | 
|fosName   | +---|fosID(FK)   | +---|pID2 (PK)  | 
+------------------+  |paperID (FK)  |--+ +-----------------+ 
(53k+ rows)    +------------------+  (952M+ rows) 
          (157M+ rows) 

Zur Zeit kann ich es tun, indem Sie einen einzelnen fosID zu meiner Anfrage liefern, aber da die fos Tabelle über 1k Datensätze enthält, ich habe nicht genug Personal, um manuell jede fosID zu füttern und erhalten ihre entsprechenden rowCount dann alle Ergebnisse verschmelzenden

declare @fosID varchar(10)='1234567890';--my fosID 

select fos.fosID,fos.fosName,count(*) as rowCount 
from PRef pr left join FOS fos on [email protected] 
where 
    pr.pID1 in(SELECT paperID FROM keywords k where [email protected]) 
    OR pr.pID2 in(SELECT paperID FROM keywords k where [email protected]) 
group by fos.fosID,fos.fosName 

dann gibt es ein korrektes Ergebnis wie:

+----------+--------+----------+ 
|fosID  |fosName |rowCount | 
+----------+--------+----------+ 
|1234567890|name1 |34  | 
+----------+--------+----------+ 

Jetzt möchte ich eine Liste aller fos bekommen i systems und Anzahl der Datensätze in PRef für jeden der 53k + fos-Artikel.

Ich habe versucht, das Teil in where [email protected] zu where k.fosID in (select fosID from FOS) geändert, aber weniger zählen wurde produziert.

Irgendwelche Vorschläge zur Lösung dieses Problems?

P.S. Ich suche jetzt bei Cursor aber die Leistung ist wirklich ... wirklich langsam

Edit 1: Erwartete Ergebnisse:

+----------+--------+----------+ 
|fosID  |fosName |rowCount | 
+----------+--------+----------+ 
|1234567890|name1 |34  | 
|1234567891|name2 |3   | 
|1234567892|name3 |23  | 
|.....  |.... |...  | 
+----------+--------+----------+ 
(exact same number of rows as table FOS) 
+0

nur um klar zu sein, wollen Sie die Zeilen der 'PRef' Tabelle zählen, die' pID1' oder 'pID2'' fosID' enthalten? – Turbot

+0

Was ist die erwartete Ausgabe? – Squirrel

+0

Ich zähle die Anzahl der Zeilen in der Tabelle 'PRef', dass entweder die Spalte' pID1' oder/und 'pID2' durch die Tabelle' keywords' in die Tabelle 'fosID' gemappt wird. – Runescapenoob

Antwort

2

Sie könnten nur Ihre Unterabfragen ändern korrelierte Unterabfragen verwenden

select fos.fosID, fos.fosName, count(*) as rowCount 
from PRef pr cross join 
     FOS fos 
where pr.pID1 in (SELECT paperID FROM keywords k where k.fosID = fos.fosID) OR 
     pr.pID2 in (SELECT paperID FROM keywords k where k.fosID = fos.fosID) 
group by fos.fosID, fos.fosName; 

Meine Vermutung ist, dass die Leistung ziemlich schlecht wäre.

ist hier eine Alternative:

select fos.*, kp.cnt 
from fos outer apply 
    (select count(*) as cnt 
     from keywords k join 
      pref pr 
      on k.paperID in (pr.pID1, pf.pID2) and 
       k.fosID = fos.fosID 
    ) kp; 

Ich kann mir vorstellen, dass dies auch ziemlich schlechte Leistungseigenschaften haben.

Wenn Sie jede ID separat tun können, dann sollte der SQL Server in der Lage sein, mit einem besseren Ausführungsplan zu kommen:

select fos.*, (kp1.cnt + kp2.cnt) 
from fos outer apply 
    (select count(*) as cnt 
     from keywords k join 
      pref pr 
      on k.paperID = pr.pID1 and 
       k.fosID = fos.fosID 
    ) kp1 outer apply 
    (select count(*) as cnt 
     from keywords k join 
      pref pr 
      on k.paperID = pr.pID2 and 
       k.fosID = fos.fosID 
    ) kp2; 
2

Zuerst habe ich vermute, dass Sie, indem Sie die Datentypen signifikante Verbesserung gewinnen könnten in Ihrem Tabellen. Es sieht so aus, als ob Sie varchar (10) nur mit numerischen Ziffern verwenden?
Diese Art von Absurdität bleibt auf kleinen Tischen unbemerkt, aber auf 900M Zeilen können mehr als 5GB verschwenden, was Speicher, Speicher und Leistung beeinträchtigt.

Sekunde FOS wird nur wirklich zum Nachschlagen verwendet fosName und bei 53k Reihen ist der kleinere Teil der Arbeit. Beginnen Sie damit, Ihre Zählungen pro fosID richtig zu machen; Dann schließe dich den Namen an.

Verwandte Themen