2017-02-02 2 views
3

Ich bin neu in der Programmierung und das ist meine erste Frage, also entschuldige ich mich, wenn ich einen Fehler mache.Wie man UND/ODER effektiv in SQL Server

ich diese Abfrage geschrieben haben:

SELECT U.Id, UWH.Role, USI.Title, CAST(USI.StartDate AS DATE) 
    FROM UserWorkHistory UWH 
    JOIN Users U ON UWH.UserId=U.Id 
    JOIN UserStoryItems USI ON U.Id=USI.UserId 
    JOIN UserWorkHistoryTypes UWHT ON UWH.UserWorkHistoryTypeId=UWHT.Id 
    WHERE U.Location LIKE '%Great Britain%' 
     OR U.Location LIKE '%United Kingdom%' 
     OR U.Location LIKE '%England%' 
     OR U.Location LIKE '%UK%' 
     OR U.Location LIKE '%U.K.%' 
     AND UWHT.Id = 1 
     AND USI.Id = 1 
     AND CAST(USI.StartDate AS DATE) > DATEADD(YEAR,-5,GETDATE()) 
     AND UWH.Role LIKE '%Contract%' 
     OR UWH.Role LIKE '%Contractor%' 
     OR UWH.Role LIKE '%Freelance%' 
     OR UWH.Role LIKE '%Non-perm%' 
     OR UWH.Role LIKE '%non-permanent%' 
     OR USI.Title LIKE '%Contractor%' 
     OR USI.Title LIKE '%Contractor%' 
     OR USI.Title LIKE '%Freelance%' 
     OR USI.Title LIKE '%Non-perm%' 
     OR USI.Title LIKE '%non-permanent%' 
     OR USI.Title LIKE '%self-made%' 

Ich versuche, vier Dinge zu spezifizieren:

1) Dass die Ergebnisse, die ich wieder aus dem Vereinigten Königreich sind erhalten

2), dass die Ergebnisse Ich bekomme zurück einige der Wörter, die ich in den "LIKE" -Argumenten angegeben habe.

3) Dass die Ergebnisse den Regeln entsprechen (UWHT.Id = 1, USI.Id = 1).

4) Dass mir nur die Ergebnisse mit einem StartDate der letzten 5 Jahre zurückgegeben werden.

Abgesehen von den Standorten, kommt nichts anderes zurück, als ich möchte. Ich könnte mir vorstellen, dass es wegen einer falschen AND/OR-Syntax ist, aber ich kann keine vorherige SO-Frage finden, die erklärt, wie man das macht (wenn es eine gibt und ich habe es verpasst, entschuldige ich mich).

+3

Mögliche Duplikat [SQL Logic Operator Präzedenz: Und und Oder] (http://stackoverflow.com/questions/1241142/sql-logic-operator-precedence-and -und-oder) –

+1

Ihre Anfrage benötigt Klammern, viele davon! – jarlh

+1

Denken Sie auch daran, die Positionsstrings, Rollen und Titel in ihren eigenen Tabellen mit einem JOIN zu verknüpfen. Auf diese Weise ist die Abfrage einfacher und es ist einfach, Dinge hinzuzufügen/zu entfernen, ohne die Abfrage selbst ändern zu müssen. –

Antwort

1

Das erste, was ich falsch sehe, ist, dass Sie keine Parens überall in Ihrer WHERE-Klausel verwenden. Sie möchten die OR s mit ihren zugehörigen AND s zur Gruppe:

WHERE 
    (U.Location LIKE '%Great Britain%' 
    OR U.Location LIKE '%United Kingdom%' 
    OR U.Location LIKE '%England%' 
    OR U.Location LIKE '%UK%' 
    OR U.Location LIKE '%U.K.%') 
AND UWHT.Id = 1 
AND USI.Id = 1 
AND CAST(USI.StartDate AS DATE) > DATEADD(YEAR,-5,GETDATE()) 
AND 
    (UWH.Role LIKE '%Contract%' 
    OR UWH.Role LIKE '%Contractor%' 
    OR UWH.Role LIKE '%Freelance%' 
    OR UWH.Role LIKE '%Non-perm%' 
    OR UWH.Role LIKE '%non-permanent%' 
    OR USI.Title LIKE '%Contractor%' 
    OR USI.Title LIKE '%Contractor%' 
    OR USI.Title LIKE '%Freelance%' 
    OR USI.Title LIKE '%Non-perm%' 
    OR USI.Title LIKE '%non-permanent%' 
    OR USI.Title LIKE '%self-made%') 

Der Grund dafür ist, dass es eine Reihenfolge der Operationen ist. Nehmen wir ein einfacheres Beispiel, auf Englisch: Was ist, wenn ich jemanden fragen möchte: "Kannst du mir eine Liste von Dingen geben, die du im Laden brauchst, die in der Molkerei sind oder auf der Tiefkühl-Insel liegen und weniger als 3 $ kosten über $ 7.00? "

Die Bedeutung davon ist mehrdeutig. Zum Beispiel könnte man das so interpretieren wie: "Können Sie mir eine Liste von Dingen geben, die auf der Milchinsel liegen (Preis spielt keine Rolle) ODER die in der gefrorenen Lebensmittelinsel sind, solange sie (die Tiefkühlkost) Artikel) kosten unter $ 3,00 oder über $ 7,00? " Sie könnten auch interpretieren es als, "Können Sie mir eine Liste von Dingen geben ... die in der Molkerei oder der Tiefkühlkost Insel sind und Kosten unter $ 3,00 oder sind in jeder Insel und Kosten über $ 7,00?"

Es gibt eine Handvoll Interpretationen außer der, die ich gerade illustriert habe. SQL Server hat Regeln, daher interpretiert er immer basierend auf einer bestimmten Reihenfolge von Operationen, die nicht unbedingt klar sein müssen und daher zu Fehlern führen. Um dies zu umgehen, verwenden Sie Parens, um eine bestimmte Interpretation zu erzwingen:

"Können Sie mir eine Liste von Dingen geben, die 1.) in der Milchinsel oder der Tiefkühl-Insel sind und 2.) kostet unter $ 3,00 oder über $ 7,00? "

+0

In der Frage, der zweite Punkt sagt (dass die Ergebnisse, die ich zurückbekomme, keine der Wörter enthalten, die ich in den "LIKE" -Argumenten angegeben habe.) Ich denke, wir müssen WIE NICHT zu WIE ändern, habe ich Recht? – balaji

+0

Brilliant, vielen Dank! – BadAtCoding

+0

@balaji Sie haben recht - ich habe tatsächlich zwei Abfragen, die identisch sind, abgesehen von einem LIKE und einem NICHT LIKE, um zwei verschiedene Ergebnisse aus demselben Datensatz zu erhalten. Ich kopierte dann und fügte den falschen in die Frage ein. Ich werde die ursprüngliche Frage bearbeiten, um dies zu ändern. Gute Stelle! – BadAtCoding

1

AND takes precedence over OR. Sie sollten Ihre Gruppe AND und OR Aussagen:

Select U.Id, 
     UWH.Role, 
     USI.Title, 
     Cast(USI.StartDate As Date) 
From UserWorkHistory  UWH 
Join Users    U On UWH.UserId = U.Id 
Join UserStoryItems  USI On U.Id = USI.UserId 
Join UserWorkHistoryTypes UWHT On UWH.UserWorkHistoryTypeId = UWHT.Id 
Where 
(
    U.Location Like '%Great Britain%' 
Or U.Location Like '%United Kingdom%' 
Or U.Location Like '%England%' 
Or U.Location Like '%UK%' 
Or U.Location Like '%U.K.%' 
) 
And UWHT.Id = 1 
And USI.Id = 1 
And Cast(USI.StartDate As Date) > DateAdd(Year, -5, GetDate()) 
And 
(
    (
     UWH.Role Like '%Contract%' 
    Or UWH.Role Like '%Contractor%' 
    Or UWH.Role Like '%Freelance%' 
    Or UWH.Role Like '%Non-perm%' 
    Or UWH.Role Like '%non-permanent%' 
    ) 
    Or 
    (
     USI.Title Like '%Contractor%' 
    Or USI.Title Like '%Contractor%' 
    Or USI.Title Like '%Freelance%' 
    Or USI.Title Like '%Non-perm%' 
    Or USI.Title Like '%non-permanent%' 
    Or USI.Title Like '%self-made%' 
    ) 
); 
+0

Das macht viel mehr Sinn, danke! – BadAtCoding

+0

Wie @Siyual angegeben, müssen Sie die Operatorrangfolge in Transact-SQL verstehen. Siehe https://msdn.microsoft.com/en-us/library/ms189773.aspx und https://msdn.microsoft.com/en-us/library/ms190276.aspx Verwenden Sie Klammern für feinere Kontrolle. Bester Rat, codieren Sie die where-Klausel Bit für Bit, Sie werden schnell lernen, wie die AND- und OR-Operatoren funktionieren. – Steve

Verwandte Themen