it-swarm.com.de

Kann ich die CASE-Anweisung in einer JOIN-Bedingung verwenden?

Das folgende Bild ist ein Teil von Microsoft SQL Server 2008 R2-Systemansichten. Das Bild zeigt, dass die Beziehung zwischen sys.partitions Und sys.allocation_units Vom Wert von sys.allocation_units.type Abhängt. Um sie zusammenzufügen, würde ich etwas Ähnliches schreiben:

SELECT  *
FROM    sys.indexes i
        JOIN sys.partitions p
            ON i.index_id = p.index_id 
        JOIN sys.allocation_units a
            ON CASE
               WHEN a.type IN (1, 3)
                   THEN a.container_id = p.hobt_id 
               WHEN a.type IN (2)
                   THEN a.container_id = p.partition_id
               END 

Der obere Code liefert jedoch einen Syntaxfehler. Ich denke, das liegt an der CASE -Anweisung. Kann jemand helfen, ein wenig zu erklären?


Fehlermeldung hinzufügen:

Meldung 102, Ebene 15, Status 1, Zeile 6 Falsche Syntax in der Nähe von '='.

this is the image

111
Just a learner

Ein CASE Ausdruck gibt einen Wert aus dem THEN Teil der Klausel zurück. Sie könnten es so verwenden:

SELECT  * 
FROM    sys.indexes i 
    JOIN sys.partitions p 
        ON i.index_id = p.index_id  
    JOIN sys.allocation_units a 
        ON CASE 
           WHEN a.type IN (1, 3) AND a.container_id = p.hobt_id THEN 1
           WHEN a.type IN (2) AND a.container_id = p.partition_id THEN 1
           ELSE 0
           END = 1

Beachten Sie, dass Sie mit dem zurückgegebenen Wert etwas tun müssen, z. Vergleichen Sie es mit 1. Ihre Anweisung hat versucht, den Wert einer Zuweisung oder eines Tests auf Gleichheit zurückzugeben, was im Kontext einer CASE/THEN -Klausel keinen Sinn ergibt. (Wenn BOOLEAN ein Datentyp wäre, wäre der Test auf Gleichheit sinnvoll.)

191
HABO

Stattdessen verbinden Sie sich einfach mit beiden Tabellen und geben in Ihrer SELECT-Klausel Daten von der Tabelle zurück, die übereinstimmt:

Ich empfehle Ihnen, diesen Link zu verwenden Bedingte Joins in SQL Server und T-SQL-Fallanweisung in einer JOIN ON-Klausel

z.B.

    SELECT  *
FROM    sys.indexes i
        JOIN sys.partitions p
            ON i.index_id = p.index_id 
        JOIN sys.allocation_units a
            ON a.container_id =
            CASE
               WHEN a.type IN (1, 3)
                   THEN  p.hobt_id 
               WHEN a.type IN (2)
                   THEN p.partition_id
               END 

Bearbeiten: Nach Kommentaren.

Sie können die Join-Bedingung währenddessen nicht angeben. Überprüfen Sie die obige Abfrage, bei der kein Fehler aufgetreten ist. Ich habe die gemeinsame Spalte herausgenommen und der richtige Spaltenwert wird unter der Bedingung ausgewertet.

31
Niranjan Singh

Versuche dies:

...JOIN sys.allocation_units a ON 
  (a.type=2 AND a.container_id = p.partition_id)
  OR (a.type IN (1, 3) AND a.container_id = p.hobt_id)
17
richardtallent

Ich denke, Sie brauchen zwei Argumente:

SELECT  *
FROM    sys.indexes i
    JOIN sys.partitions p
        ON i.index_id = p.index_id 
    JOIN sys.allocation_units a
        ON 
        -- left side of join on statement
            CASE
               WHEN a.type IN (1, 3)
                   THEN a.container_id
               WHEN a.type IN (2)
                   THEN a.container_id
            END 
        = 
        -- right side of join on statement
            CASE
               WHEN a.type IN (1, 3)
                   THEN p.hobt_id
               WHEN a.type IN (2)
                   THEN p.partition_id
            END             

Das ist weil:

  • die CASE-Anweisung gibt am ENDE einen einzelnen Wert zurück
  • die ON-Anweisung vergleicht zwei Werte
  • ihre CASE-Anweisung hat den Vergleich durchgeführt innerhalb der CASE-Anweisung. Ich würde vermuten, dass Sie, wenn Sie Ihre CASE-Anweisung in Ihre SELECT-Anweisung einfügen, eine boolesche '1' oder '0' erhalten, die angibt, ob die CASE-Anweisung mit True oder False bewertet wurde
8
DonkeyKong

Das scheint nett zu sein

https://bytes.com/topic/sql-server/answers/881862-joining-different-tables-based-condition

FROM YourMainTable
LEFT JOIN AirportCity DepCity ON @TravelType = 'A' and DepFrom =  DepCity.Code
LEFT JOIN AirportCity DepCity ON @TravelType = 'B' and SomeOtherColumn = SomeOtherColumnFromSomeOtherTable
1
user4584103

Ich habe dein Beispiel genommen und es bearbeitet:

SELECT  *
FROM    sys.indexes i
    JOIN sys.partitions p
        ON i.index_id = p.index_id 
    JOIN sys.allocation_units a
        ON CASE
           WHEN a.type IN (1, 3)
               THEN p.hobt_id 
           WHEN a.type IN (2)
               THEN p.partition_id
           ELSE NULL
           END = a.container_id
1
Gont

Hier habe ich den Unterschied zwischen zwei verschiedenen Ergebnismengen verglichen. Hoffe das könnte hilfreich sein.

SELECT main.ColumnName, compare.Value PreviousValue,  main.Value CurrentValue
FROM 
(
    SELECT 'Name' AS ColumnName, 'John' as Value UNION ALL
    SELECT 'UserName' AS ColumnName, 'jh001' as Value UNION ALL
    SELECT 'Department' AS ColumnName, 'HR' as Value UNION ALL
    SELECT 'Phone' AS ColumnName, NULL as Value UNION ALL
    SELECT 'DOB' AS ColumnName, '1993-01-01' as Value UNION ALL
    SELECT 'CreateDate' AS ColumnName, '2017-01-01' as Value UNION ALL
    SELECT 'IsActive' AS ColumnName, '1' as Value
) main
INNER JOIN
(
    SELECT 'Name' AS ColumnName, 'Rahul' as Value UNION ALL
    SELECT 'UserName' AS ColumnName, 'rh001' as Value UNION ALL
    SELECT 'Department' AS ColumnName, 'HR' as Value UNION ALL
    SELECT 'Phone' AS ColumnName, '01722112233' as Value UNION ALL
    SELECT 'DOB' AS ColumnName, '1993-01-01' as Value UNION ALL
    SELECT 'CreateDate' AS ColumnName, '2017-01-01' as Value UNION ALL
    SELECT 'IsActive' AS ColumnName, '1' as Value
) compare
ON main.ColumnName = compare.ColumnName AND
CASE 
    WHEN main.Value IS NULL AND compare.Value IS NULL THEN 0
    WHEN main.Value IS NULL AND compare.Value IS NOT NULL THEN 1
    WHEN main.Value IS NOT NULL AND compare.Value IS NULL THEN 1
    WHEN main.Value <> compare.Value THEN 1
END = 1 
0
Sheikh Kawser

Nahm DonkeyKongs Beispiel.

Das Problem ist, dass ich eine deklarierte Variable verwenden muss. Auf diese Weise können Sie Ihre linke und rechte Seite angeben, was Sie vergleichen möchten. Dies dient zur Unterstützung eines SSRS-Berichts, bei dem je nach Auswahl des Benutzers verschiedene Felder verknüpft werden müssen.

Der erste Fall legt die Feldauswahl basierend auf der Auswahl fest und dann kann ich das Feld festlegen, auf das ich für den Join passen muss.

Eine zweite case-Anweisung könnte für die rechte Seite hinzugefügt werden, wenn die Variable zur Auswahl aus verschiedenen Feldern benötigt wird

LEFT OUTER JOIN Dashboard_Group_Level_Matching ON
       case
         when @Level  = 'lvl1' then  cw.Lvl1
         when @Level  = 'lvl2' then  cw.Lvl2
         when @Level  = 'lvl3' then  cw.Lvl3
       end
    = Dashboard_Group_Level_Matching.Dashboard_Level_Name
0
Kenneth Wilson