CASE deyimini JOIN koşulunda kullanabilir miyim?


141

Aşağıdaki görüntü, Microsoft SQL Server 2008 R2 Sistem Görünümlerinin bir parçasıdır. Görüntüden sys.partitionsve arasındaki ilişkinin sys.allocation_unitsdeğerine bağlı olduğunu görebiliriz sys.allocation_units.type. Birlikte onlara katılmak için buna benzer bir şey yazardım:

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 

Ancak üst kod sözdizimi hatası verir. Sanırım bu CASEaçıklama yüzünden . Herkes biraz açıklamaya yardımcı olabilir mi?


Hata mesajı ekle:

Msg 102, Seviye 15, Durum 1, Satır 6 '=' yakınında yanlış sözdizimi.

bu görüntü


36
Bu güzel DB diyagramını yapmak için hangi yazılımı kullandınız?
LearnByReading

2
@LearnByReading hangi yazılımın kullanıldığını buldunuz mu?
Kullanıcı632716

1
@ User632716 maalesef hayır!
LearnByReading

2
@ User632716 Her ne kadar gerçekten MySQL Workbench olduğunu düşünüyorum. Ama hiç bir yanıt almadım
LearnByReading

@LearnByReading Hiçbir fikrim yok. Microsoft tarafından sağlanır.
Sadece bir öğrenci

Yanıtlar:


223

Bir CASEifade THEN, maddenin yan tümcesinden bir değer döndürür . Bu şekilde kullanabilirsiniz:

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

Döndürülen değerle bir şey yapmanız gerektiğini unutmayın, örneğin 1 ile karşılaştırın. İfadeniz, her ikisi de a CASE/ THENyan tümcesi bağlamında anlamlı olmayan bir ödevin veya eşitlik testinin değerini döndürmeye çalıştı . (Eğer BOOLEANbir veri tipi olsaydı , eşitlik testi mantıklı olurdu.)


@HABO benim için çalıştı teşekkürler ... ama sorun bunu yaptığımda koşulları bir düşüş yapmak ... lütfen bana nasıl kırmak söyle?
Sagar Tandel

1
@SagarTandel - Üzgünüm, "bir düşüş yap" ve "onu nasıl kırabilirim" anlamıyorum. Yorumunuzu netleştirebilir misiniz? (Son zamanlarda Saba kapalı bir dalıştan ortaya çıktı. Nitrox olabilir.)
HABO

İstemediğim tüm koşulları kontrol eder. Bir koşulla eşleştiğinde davayı bırakmasını istiyorum.
Sagar Tandel

3
@SagarTandel - MSDN'den : "CASE deyimi koşullarını sırayla değerlendirir ve koşulu karşılanan ilk koşulla durur.". Açıkça belirtilen koşullardan hiçbiriyle eşleşmeyen tüm birleştirilen satırları istiyorsanız, kuyruk sonunu olarak = 1değiştirin = 0, ancak sonucu beğeneceğinizi düşünmüyorum.
HABO

S. Varlık çerçevesine çözümünüzün yukarısında yazabilir misiniz
r.hamd

36

Bunun yerine, her iki tabloya KATILIN ve SELECT yan tümcenizde, eşleşen tablodan veri döndürün:

Bu bağlantıyı SQL Server'daki Koşullu Bağlantılar ve JOIN ON Cümlesindeki T-SQL Durum Bildirimi üzerinden geçirmenizi öneririm

Örneğin

    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 

Düzenleme: Yorumlara göre.

Birleştirme koşulunu yaptığınız gibi belirtemezsiniz. Yukarıdaki hatayı olmayan sorguyu kontrol edin. Ortak sütunu yukarı kaldırdım ve doğru sütun değeri koşulda değerlendirilecektir.


1
ne conditional joindemek Her birleştirme (çapraz hariç) bir şarttır. Bu dava diğerlerinden nasıl farklı? Numuneniz koşulla iç birleşimin yanı sıra OPs sorgusu koşulla birleşmiştir.
zerkms

@zerkms: Katılıyorum, kafa karıştırıcı geliyor. Ben, iman koşullu katılmak Bu bağlamda bir olan durum başka durumuna bağlıdır katılmak anlamına içinde.
Andriy M

@Andriy M: Önemsiz bir durum için başka bir terim düşünmek için herhangi bir neden OR?
zerkms

@zerkms: Ee, evet, kafa karıştırıcı geldiği için. :) Ama herhangi bir neden olmadığını sormak istedim inanmak değil ben emin olamaz ve bu durumda başka bir terim, düşün. Eğer soran varsa benim nedenlerle, pekala, ben yeterince rahatsız olamazdı düşünüyorum. :) Alternatif koşullara katılmaya ne dersiniz ? Korkarım, terim açısından çok iyi değilim. Bununla birlikte, kavramsal olarak bunun "koşullu koşul" ile ilgili olduğunu, "koşullu koşul" ile ilgili olmadığını unutmayın OR. Kullanmak ORsadece uygulamanın bir yoludur.
Andriy M

@Andriy M: tamam. Ama şahsen hala 1 ve 2 veya 1 ile önemsiz durum için bir isim vermenin nedenini göremiyorum . Diğerlerinden farklı hiçbir şeyi olmayan rutin bir sorgudur. ORANDsCASE
zerkms

17

Bunu dene:

...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)

Çalışmasına rağmen - sorudaki sorgu tamamen geçerli görünüyor. Hala OP kodunda neyin yanlış olduğunu açıklamıyor
zerkms

10

Bence iki vaka ifadesine ihtiyacınız var:

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             

Bunun nedeni ise:

  • CASE deyimi END'de tek bir değer döndürür
  • ON ifadesi iki değeri karşılaştırır
  • CASE ifadeniz, CASE ifadesinin içindeki karşılaştırmayı yapıyordu . CASE ifadenizi SELECT öğenize koyarsanız, CASE ifadesinin True veya False olarak değerlendirilip değerlendirilmediğini gösteren bir boole '1' veya '0' elde edeceğinizi tahmin ediyorum.

5

Örneğini aldım ve düzenledim:

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
           ELSE NULL
           END)


1

Evet yapabilirsin. İşte bir örnek.

SELECT a.*
FROM TableA a
LEFT OUTER JOIN TableB j1 ON  (CASE WHEN LEN(COALESCE(a.NoBatiment, '')) = 3 
                                THEN RTRIM(a.NoBatiment) + '0' 
                                ELSE a.NoBatiment END ) = j1.ColumnName 

1
Bu kod, sorunun nasıl ve neden çözüldüğüne dair bir açıklama da dahil olmak üzere soruyu çözebilir, ancak gönderinizin kalitesini artırmaya yardımcı olabilir ve muhtemelen daha fazla oyla sonuçlanır. Sadece şimdi soran kişi için değil, gelecekte okuyucular için soruyu cevapladığınızı unutmayın. Lütfen açıklama eklemek için cevabınızı düzenleyin ve hangi sınırlamaların ve varsayımların geçerli olduğunu belirtin.
çift ​​bip

0

DonkeyKong örneğini aldı.

Sorun bildirilen bir değişken kullanmak için gerekli olmasıdır. Bu, karşılaştırmanız gerekenlerin sol ve sağ tarafını belirtmenize olanak tanır. Bu, kullanıcının seçimine bağlı olarak farklı alanların bağlanması gereken bir SSRS raporunu desteklemek içindir.

İlk durum, alan seçimini seçime göre belirler ve ardından birleştirme için eşleşmem gereken alanı ayarlayabilirim.

Değişkenin farklı alanlardan seçim yapması gerekiyorsa sağ taraf için ikinci bir vaka ifadesi eklenebilir

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

Burada iki farklı sonuç kümesindeki farkı karşılaştırdım:

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 
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.