Frage

Ich habe eine Primärtabelle für die Artikel, die durch eine Join-Tabelle an einen Tisch Schlagwörter verknüpft ist, die nur eine geringe Anzahl von Einträgen haben. Ich möchte den Artikel Tisch teilen, entweder durch Löschen von Zeilen oder Erstellen einer neuen Tabelle mit nur den Einträgen Ich möchte, bezogen auf das Fehlen eines Links zu einem bestimmten Tag. Es gibt ein paar Millionen Artikel. Wie kann ich das tun?

Nicht alle Gegenstände haben einen beliebigen Tag überhaupt, und einige haben viele Tags.

Beispiel:

table Articles
  primary_key id
table Info
  foreign_key article_id
  foreign_key tag_id
table Tags
  primary_key id

Es war einfach für mich, um die Artikel zu trennen, die das Spiel direkt von der Fledermaus zu tun haben, so dass ich vielleicht dachte, ich könnte das tun und dann eine NICHT-Anweisung verwenden, aber die so langsam läuft es unklar ist, ob es überhaupt geht zu Fertig. Das habe ich mit diesen Befehlen:

INSERT INTO matched_articles SELECT * FROM articles a LEFT JOIN info i ON a.id = i.article_id WHERE i.tag_id = 5;
INSERT INTO unmatched_articles SELECT * FROM articles a WHERE a.id NOT IN (SELECT m.id FROM matched_articles m);

Wenn es einen Unterschied macht, ich bin auf Postgres.

War es hilfreich?

Lösung

INSERT INTO matched_articles 
SELECT * FROM articles a LEFT JOIN info i ON a.id = i.article_id WHERE i.tag_id = 5; 

INSERT INTO unmatched_articles 
SELECT * FROM articles a WHERE a.id NOT IN (SELECT m.id FROM matched_articles m); 

Es gibt so viel falsch hier, ich bin nicht sicher, wo ich anfangen soll. OK in Ihrem ersten Einsatz brauchen Sie nicht nach links in der Tat kommen Sie eigentlich noch kein Konto haben. Es sollte sein

INSERT INTO matched_articles 
SELECT * FROM articles a INNER JOIN info i ON a.id = i.article_id WHERE i.tag_id = 5; 

Hatten Sie benötigten beitreten eine linke Sie hätte, wenn

INSERT INTO matched_articles 
SELECT * FROM articles a LEFT JOIN info i ON a.id = i.article_id AND i.tag_id = 5; 

Wenn Sie etwas von der rechten Seite eines linken setzen beitreten in die where-Klausel (außer für die Nullwerte der Suche), dann sind Sie es zu einem inneren konvertieren beitreten becasue es diese Bedingung erfüllen muss, damit die Aufzeichnungen, dass don‘ t haben eine Übereinstimmung inder rechten Tabelle sind elimiated.

Nun ist die zweite Aussage kann mit einem Sonderfall der LEFT JOIN getan werden, obwohl das, was Sie haben, arbeiten.

INSERT INTO matched_articles 
SELECT * FROM articles a 
LEFT JOIN info i ON a.id = i.article_id AND i.tag_id = 5
WHERE i.tag_id is null

Dies wird Ihnen alle Datensätze, die mit Ausnahme der in der Info-Tabelle sind, dass abgestimmte der Artikel-Tabelle.

Nun ist die nächste Sache, sollten Sie nicht Einsatz staments schreiben, ohne die Felder spezifizieren Sie einfügen möchten. Auch sollten Sie jemals eine select-Anweisung select * schreiben vor allem, wenn Sie eine Verknüpfung haben. Dies ist im Allgemeinen schlampig, faul Codierung und soll festgelegt werden. Was passiert, wenn jemand die Struktur einer der Tabellen geändert, aber nicht die anderen? Diese Art der Sache ist schlecht für die Wartung und im Fall einer ausgewählten statment mit einem Join, es kehrt einen collumn zweimal (die Join-Spalte), und das ist eine Verschwendung von Server- und Netzwerkressourcen. Es ist Codierung nur schlecht zu faul zu sein, festzulegen, was Sie brauchen, und nur das, was Sie brauchen. Also raus aus der Gewohnheit und tun es nicht wieder für jeden Produktionscode.

Wenn Sie aktuelle abgetan zu langsam ist, können Sie auch in der Lage sein, es mit dem richtigen Indizes zu beheben. Sind die ID-Felder auf beiden Tabellen indiziert? Onthe andere Seite, wenn es millionas von Artikeln ist, wird es Zeit in Anspruch nehmen, sie einzusetzen. Oft ist es besser, dies vielleicht 50000 zu einer Zeit, in Chargen zu tun (noch weniger, wenn dies zu lange dauert). Nur tun, um den Einsatz ina Schleife wählt, dass die oberen XXX Aufzeichnungen und dann in einer Schleife, bis die Zeilenanzahl betroffen ist kein.

Andere Tipps

Ihre Anfragen aussehen ok, außer die erste eine innere Verknüpfung sein sollte, kein LEFT JOIN. Wenn Sie etwas anderes ausprobieren möchten, bedenken Sie:

INSERT INTO matched_articles 
SELECT * 
FROM articles a 
INNER JOIN info i ON a.id = i.article_id 
WHERE i.tag_id = 5;

INSERT INTO unmatched_articles 
SELECT * 
FROM articles a 
LEFT JOIN info i ON a.id = i.article_id AND a.id <> 5
WHERE a.id IS NULL

Das könnte schneller sein, aber wirklich, was Sie haben, ist wahrscheinlich in Ordnung, wenn Sie es nur einmal zu tun haben.

Nicht sicher, ob Postgres hat ein Konzept einer temporären Tabelle.
Hier ist, wie dies getan werden kann, wie gut.

CREATE Table #temp
AS SELECT A.ID, COUNT(i.*) AS Total
FROM Articles A
LEFT JOIN info i
ON A.id = i.Article_ID AND i.Tag_ID = 5
GROUP BY A.ID

INSERT INTO Matched_Articles
SELECT A.*
FROM Articles A INNER JOIN #temp t
ON A.ID = t.Article_ID AND T.Total = 0

DELETE FROM #Temp
WHERE Total = 0

INSERT INTO UnMatched_Articles
SELECT A.*
FROM Articles AINNER JOIN #temp t
ON A.ID = t.Article_ID

Beachten Sie, dass ich nicht mit einem beliebigen Editor mit diesem heraus zu versuchen.
Ich hoffe, das gibt Ihnen andeuten, wie ich dies würde nähern.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top