2016-07-07 11 views
1

Ich muss Tabelle aktualisieren, die auf zwei weitere Tabellen verweist.Update-Tabelle mit 2 Join

Hier ist mein Auswahlcode um zu überprüfen, welche Zeilen aktualisiert werden.

SELECT * 
FROM txsh AS t1 
     INNER JOIN div AS t2 ON t2.store = t1.ro_no 
     INNER JOIN temp_db AS t3 ON t3.bpn = t1.sku_id 
        AND (t3.div IS NULL OR t3.div = t2.div) 
        AND (t3.s_num IS NULL OR t3.s_num = t1.ro_no) 

enter image description here

Dies ist das Ergebnis der drei Tabellen, die ich verbunden. Die Spalte 'div' stammt aus der Tabelle div, die von ro_no abhängt, während 'bpn, s_num, created_by' aus der Tabelle temp_db stammt.

Jetzt möchte ich alle ausgewählten Zeilen aus meinem Auswahlcode aktualisieren. Hier ist mein Update-Code.

UPDATE  txsh 
SET   price = '0' 
FROM   txsh AS t1 
      INNER JOIN temp_db AS t2 ON t1.sku_id = t2.bpn 
      CROSS JOIN div AS t3 
      CROSS JOIN txsh 
WHERE  (t2.div IS NULL OR t3.div = t2.div) 
      AND (t2.s_num IS NULL OR t2.s_num = t1.ro_no) 

Ich habe drei Instanzen für das Update. Es hängt von temp_db (BPN, s_num, div)

  1. wenn s_num und div null ist, zu aktualisieren txsh wo sku_id = bpn
  2. wenn s_num nicht null ist und div ist null, update txsh wo sku_id = bpn und ro_no = s_num
  3. Wenn s_num null ist und div nicht null ist, txsh aktualisieren, wobei sku_id = bpn und [ro_no] 's div-Wert aus Tabelle div [t2] gleich temp_db [div] -Wert ist.

Ich denke, dass der Fehler auf Instanz [3] ist. Gibt es eine Möglichkeit, meine Where-Klausel zum Beispiel [3] zu korrigieren?

+4

Warum in der Welt sind Sie Kreuz Beitritt zu Txsh? Wenn Sie diesen Cross-Join entfernen und das UPDATE stattdessen auf "t1" setzen, funktioniert Ihre Abfrage dann? –

+1

Ich werde das deutlicher machen; Wenn Sie froh sind, dass Ihre erste Abfrage wie gewünscht funktioniert, entfernen Sie einfach die "SELECT *" von Anfang an, ersetzen Sie dies durch "UPDATE txsh SET price = '0'" und Sie sollten gut gehen. Ein CROSS JOIN bringt nur jede Zeile in dieser Tabelle zurück, so dass Ihre zweite Abfrage nur jeden Datensatz in txsh aktualisiert, der Rest der Abfrage ist völlig redundant und wird wahrscheinlich sowieso vom Optimierer ignoriert. –

+0

Es ist völlig normal, dass zwei völlig verschiedene Abfragen unterschiedliche Ergebnisse haben. Wenn die gleiche deterministische Abfrage nun andere Ergebnisse liefert, wäre das unerwartet. –

Antwort

2

Okay, das ist immer zu lang für ein Gespräch, so dass ich es in eine Antwort setzen stattdessen ...

Das ist Ihre ursprüngliche Abfrage, leicht umformatiert, um es einfacher zu lesen:

SELECT 
    t1.* 
FROM  
    txsh t1 
    INNER JOIN div t2 ON t2.store = t1.ro_no 
    INNER JOIN temp_db t3 ON t3.bpn = t1.sku_id 
     AND ISNULL(t3.div, t2.div) = t2.div 
     AND ISNULL(t3.s_num, t1.ro_no) = t1.ro_no; 

Wenn Sie diese Abfrage ausführen, wird es eine bestimmte Anzahl von Zeilen zurück, könnte es jede Zeile von txsh zurückzukehren, oder es könnte eine Teilmenge der Zeilen zurück, da es zwei Einschränkungen (INNER JOIN-Bedingungen).

Dann gibt es die zusätzliche Komplexität, dass diese INNER JOINs mehr als einen Datensatz von txsh einbringen können, so dass die Zeilenanzahl höher sein könnte als die Anzahl der Zeilen in txsh. Zum Beispiel könnte es 10 Zeilen in div geben, wo store = 10 und eine Zeile in txsh, wo ro_no = 10 (Ich kenne Ihre Daten nicht, vielleicht ist das nicht möglich?). In diesem Szenario könnten Sie 10 doppelte Zeilen von txsh für jede einzelne Zeile von Daten haben, wobei store = 10 ist.

Also meine erste Frage ist, wie viele Zeilen von dieser Abfrage zurückgegeben werden, und ist dies das erwartete Ergebnis? Idealerweise gibt es keine Duplikationsprobleme, und die Antwort lautet, dass die Abfrage zwischen null und der Anzahl der Zeilen in txsh zurückkehrt.

Ihre Update-Abfrage sollte nun so einfach wie:

UPDATE 
    t1 
SET 
    price = '0' 
FROM  
    txsh t1 
    INNER JOIN div t2 ON t2.store = t1.ro_no 
    INNER JOIN temp_db t3 ON t3.bpn = t1.sku_id 
     AND ISNULL(t3.div, t2.div) = t2.div 
     AND ISNULL(t3.s_num, t1.ro_no) = t1.ro_no; 

Beim Ausführen dieses es wird Ihnen sagen, wie viele Zeilen aktualisiert wurden, ist dies die gleiche Anzahl von Zeilen, die Ihre SELECT-Abfrage zurückgegeben?

Wenn Sie diese beiden Fragen beantworten können, dann können wir hoffentlich dieses Problem zu beheben weitergehen?

Okay, ich bin immer noch etwas ungläubig, dass die SELECT-Abfrage 7 Zeilen zurückgibt und die UPDATE 10 Zeilen aktualisiert ... aber wir versuchen es als Ausgangspunkt. Ich habe deine Logik so einfach wie möglich geschrieben. Wenn das funktioniert, können wir die Abfrage wahrscheinlich etwas umgestalten?

UPDATE 
    t1 
SET 
    price = '0' 
FROM  
    txsh t1 
    INNER JOIN div t2 ON t2.store = t1.ro_no 
    INNER JOIN temp_db t3 ON t3.bpn = t1.sku_id 
WHERE 
    --Case 1 
    (t3.div IS NULL AND t3.s_num IS NULL) 
    --Case 2 
    OR (t3.div IS NULL AND t3.s_num IS NOT NULL AND t3.s_num = t1.ro_no) 
    --Case 3 
    OR (t3.div IS NOT NULL AND t3.s_num IS NULL AND t3.div = t2.div); 

So ist die INNER JOIN temp_db ist jetzt nur auf BBP sku_id, wie dies in Ihren drei Fällen konstant ist. Ich fügte den Rest der Logik für jeden Fall in die WHERE-Klausel ein.

Ich würde versuchen, dies als eine SELECT-Abfrage zuerst ausführen, dann versuchen Sie die UPDATE?

+0

Vielen Dank für Ihre Hilfe, aber es aktualisiert immer noch alle Zeilen. Ursprünglich müssen 7 Zeilen nur aktualisiert werden. die Abfrage aktualisiert alle 10 Zeilen –

+0

Ich denke, dass mein Problem auf ISNULL ist (t3.div, t2.div) = t2.div t1 enthält 'ro_no', die 'div' Wert von t2 hat. Ich möchte aktualisieren, Zeilen, bei denen t3 Spalte 'div' gleich t1 (ro_no) 'div' Wert ist. –

+0

Haben Sie Zeilen in [temp_db], die sowohl für [div] als auch für [s_num] einen NULL-Wert haben? Dies ist das Bit, das möglicherweise problematisch scheint. Wenn Sie sagen, dass alle zehn Zeilen aktualisiert werden, haben Sie dies überprüft, oder sehen Sie nur eine Meldung "10 Zeilen betroffen", wenn Sie UPDATE ausführen? Da Sie scheinbar nicht viele Daten haben, besteht die Möglichkeit, dass Sie dies zu Ihrer Frage hinzufügen könnten. –