2016-07-15 14 views
1

Mein INNERER JOIN filtert zu viel heraus oder ich kann nicht sehen, was der Unterschied ist.Mein INNERER JOIN filtert zu viel heraus

Ich versuche, 2 Tabellen aus 2 verschiedenen Datenbanken auf demselben Server zu konsolidieren.

Mein erster Schritt ist es, alle Werte zu finden, die passen:

SELECT intl.* 
FROM tblData intl 
INNER JOIN [db].dbo.tblData us 
ON  intl.DataID = us.DataID 
AND intl.AnotherID = us.AnotherID 
AND intl.DataValue = us.DataValue 
AND intl.TextValue = us.TextValue 
AND intl.DefaultValue = us.DefaultValue 
AND intl.RateValue = us.RateValue 
AND intl.YetAnotherID = us.YetAnotherID 

ich alle Spalten überprüft haben, und sie sind die gleichen Typs und gleicher varchar Werte. Diese Abfrage sollte also alle übereinstimmenden Werte zurückgeben.

Allerdings ... Das ist nicht der Fall. Es kehrt nur 200+ Aufzeichnungen, wo, wenn ich diese Abfrage ausführen, nachdem ich die 200+ Datensätze in eine temporäre Tabelle einfügen:

SELECT intl.DataID 
FROM tblData intl 
LEFT JOIN TempDataTable TDT 
ON  TDT.DataID = intl.DataID 
AND TDT.AnotherID = intl.AnotherID 
AND TDT.DataValue = intl.DataValue 
AND TDT.TextValue = intl.TextValue 
AND TDT.DefaultValue = intl.DefaultValue 
AND TDT.RateValue = intl.RateValue 
AND TDT.YetAnotherID = intl.YetAnotherID 
WHERE TDT.DataID IS NULL 

Diese Abfrage 1500 Zeilen zurückgibt.

Ich habe eine ähnliche Abfrage mit den US-Daten ausgeführt und die gleiche Diskrepanz gefunden (1500+ Zeilen zurückgegeben).

Ich schaute auf 1 Datensatz nur um zu sehen, ob ich etwas whacky identifizieren konnte, und ich fand, dass die Datensätze von jeder Tabelle (INTL und US) GENAU die gleichen sind!

Ich stelle mir vor, dass meine innere Verbindung einen Unterschied zwischen den 2 Tabellen strukturell findet, aber ich kann es nicht sehen.

Irgendwelche Ideen zu was würde dies verursachen?

+4

wahrscheinlich die 'NULL' Werte. 'NULL' ist nichts, nicht einmal ein' NULL'.Also, wo es die 'NULL'-Spalten vergleicht, würde es die Gleichheitsprüfung fehlschlagen und auf diese Weise Ihre' LINKEN JOIN'-Nummern aufblasen. – Siyual

+0

Wirklich ... das wusste ich nicht. Haben Sie irgendwelche Vorschläge, um dies zum Laufen zu bringen oder sollte ich die Spalten, die überhaupt NULL sein könnten, nicht anpassen? – webdad3

+2

Eine Möglichkeit, dies zu handhaben, besteht darin, diese Nullen in reale Werte umzuwandeln: 'coalesce (TDT.DataValue, '! @ # $%') = Koaleszieren (TDT.DataValue, '! @ # $%')' – shawnt00

Antwort

2

Dies wird wahrscheinlich durch die NULL Werte verursacht, die Sie in der Tabelle bei der Überprüfung der Gleichheit Ihrer LEFT JOIN haben.

NULL Werte sind nicht gleich zu nichts, nicht einmal zu einem anderen NULL des gleichen Datentyps.

Um dies zu beheben, können Sie einen Scheck an den ON Klausel für NULL Werte auf beiden Seiten zusätzlich zu den bestehenden JOIN Bedingungen hinzufügen:

SELECT intl.DataID 
FROM tblData intl 
LEFT JOIN TempDataTable TDT 
    ON (
      (TDT.DataID IS NULL AND intl.DataID IS NULL)    
      OR TDT.DataId = intl.DataId 
     ) 
    AND (
      (TDT.AnotherID IS NULL AND intl.AnotherID IS NULL)  
      OR TDT.AnotherId = intl.AnotherId 
     ) 
    AND (
      (TDT.DataValue IS NULL AND intl.DataValue IS NULL)  
      OR TDT.DataValue = intl.DataValue 
     ) 
    AND (
      (TDT.TextValue IS NULL AND intl.TextValue IS NULL)  
      OR TDT.TextValue = intl.TextValue 
     ) 
    AND (
      (TDT.DefaultValue IS NULL AND intl.DefaultValue IS NULL) 
      OR TDT.DefaultValue = intl.DefaultValue 
     ) 
    AND (
      (TDT.RateValue IS NULL AND intl.RateValue IS NULL) 
      OR TDT.RateValue = intl.RateValue 
     ) 
    AND (
      (TDT.YetAnotherID IS NULL AND intl.YetAnotherID IS NULL) 
      OR TDT.YetAnotherID = intl.YetAnotherID 
     ) 
WHERE TDT.DataID IS NULL 
1

Sie INNER JOIN tut, was es soll und dass kehrt Nur Zeilen von tblData (us) und tblData (international), wo alle Ihrer tdt = intl Bedingungen gelten. Wenn es ein NULL Wert ist, dann wäre coalesce(), was Sie verwenden möchten. Stellen Sie sich Folgendes vor:

1

EXISTS kann für diese Abfrage gut sein.

SELECT 
    intl.DataID 
FROM 
    tblData intl 
WHERE 
    NOT EXIST 
    (
     SELECT TOP 1 FROM TempDataTable TDT 
     WHERE 
      TDT.DataID = intl.DataID AND 
      TDT.AnotherID = intl.AnotherID AND 
      TDT.DataValue = intl.DataValue AND 
      TDT.TextValue = intl.TextValue AND 
      TDT.DefaultValue = intl.DefaultValue AND 
      TDT.RateValue = intl.RateValue AND 
      TDT.YetAnotherID = intl.YetAnotherID 
    ) 
2

Ich mag diesen Ansatz zum Umgang mit NULL Gleichheitsvergleiche.

More details about it here

SELECT intl.* 
FROM tblData intl 
     INNER JOIN [db].dbo.tblData us 
     ON EXISTS (SELECT intl.DataID, 
          intl.AnotherID, 
          intl.DataValue, 
          intl.TextValue, 
          intl.DefaultValue, 
          intl.RateValue, 
          intl.YetAnotherID, 
        INTERSECT 
        SELECT us.DataID, 
          us.AnotherID, 
          us.DataValue, 
          us.TextValue, 
          us.DefaultValue, 
          us.RateValue, 
          us.YetAnotherID) 
2
Values null not take in your query. Use isnull(value, 0) for type value number and isnull(value, '') for type value chararctere 

    SELECT intl.DataID 
    FROM tblData intl 
    inner JOIN TempDataTable TDT 
    ON  isnull(TDT.DataID, 0) = isnull(intl.DataID, 0) 
    AND isnull(TDT.AnotherID, 0) = isnull(intl.AnotherID, 0) 
    AND isnull(TDT.DataValue, '') = isnull(intl.DataValue, '') 
    AND isnull(TDT.TextValue, '') = isnull(intl.TextValue, '') 
    AND isnull(TDT.DefaultValue, 0) = isnull(intl.DefaultValue, 0) 
    AND isnull(TDT.RateValue, '') = isnull(intl.RateValue, '') 
    AND isnull(TDT.YetAnotherID, 0) = isnull(intl.YetAnotherID, 0) 
Verwandte Themen