Bisakah saya menggunakan pernyataan KASUS dalam kondisi BERGABUNG?


141

Gambar berikut adalah bagian dari Tampilan Sistem Microsoft SQL Server 2008 R2. Dari gambar tersebut kita dapat melihat bahwa hubungan antara sys.partitionsdansys.allocation_units tergantung pada nilai sys.allocation_units.type. Jadi untuk bergabung dengan mereka, saya akan menulis sesuatu yang mirip dengan ini:

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 

Tetapi kode bagian atas memberikan kesalahan sintaksis. Saya kira itu karenaCASE pernyataan itu. Adakah yang bisa menjelaskan sedikit?


Tambahkan pesan kesalahan:

Msg 102, Level 15, Negara 1, Baris 6 Sintaks salah dekat '='.

ini adalah gambar


36
Perangkat lunak apa yang Anda gunakan untuk membuat diagram DB yang indah ini?
LearnByReading

2
@LearnByReading apakah Anda pernah menemukan perangkat lunak mana yang digunakan?
User632716

1
@ User632716 sayangnya tidak!
LearnByReading

2
@ User632716 Meskipun saya benar-benar berpikir itu adalah Workbench MySQL. Tetapi saya tidak pernah menerima jawaban
LearnByReading

@PelajariByReading Saya tidak tahu. Ini disediakan oleh Microsoft.
Baru belajar

Jawaban:


223

Sebuah CASEekspresi mengembalikan nilai dari THENbagian klausa. Anda dapat menggunakannya sebagai berikut:

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

Perhatikan bahwa Anda perlu melakukan sesuatu dengan nilai yang dikembalikan, misalnya membandingkannya dengan 1. Pernyataan Anda berupaya mengembalikan nilai tugas atau menguji kesetaraan, yang keduanya tidak masuk akal dalam konteks a CASE/ THENklausa. (Jika BOOLEANitu tipe data maka tes untuk kesetaraan akan masuk akal.)


@HABO terima kasih yang bekerja untuk saya ... tetapi masalahnya adalah ketika saya melakukan ini, kondisi membuat jatuh ... tolong katakan padaku bagaimana cara melanggarnya?
Sagar Tandel

1
@SagarTandel - Maaf, saya tidak mengerti "jatuh" dan "bagaimana saya melanggarnya". Bisakah Anda mengklarifikasi komentar Anda? (Baru-baru ini muncul dari penyelaman di Saba. Mungkin Nitrox.)
HABO

Ia memeriksa semua kondisi yang tidak saya inginkan. Saya ingin keluar dari kasing setelah cocok dengan suatu kondisi.
Sagar Tandel

3
@SagarTandel - Dari MSDN : "Pernyataan CASE mengevaluasi kondisinya secara berurutan dan berhenti dengan kondisi pertama yang kondisinya terpenuhi.". Jika Anda ingin semua baris yang digabung yang tidak cocok dengan kondisi yang dinyatakan secara eksplisit, ubah saja ujung ekor dari = 1menjadi = 0, tetapi saya tidak berpikir Anda akan menyukai hasilnya.
HABO

GABUNG sys.allocation_units KASUS PADA SAAT a.type IN (1, 3) DAN a.container_id = p.hobt_id KEMUDIAN 1 SAAT a.type IN (2) DAN a.container_id = p.partition_id THEN 1 ELSE 0 END = 1 dapatkah Anda menuliskannya dalam kerangka Entitas di atas solusi Anda
r.hamd

36

Sebagai gantinya, Anda cukup BERGABUNG ke kedua tabel, dan dalam klausa SELECT Anda, kembalikan data dari yang cocok:

Saya sarankan Anda untuk pergi melalui tautan ini Conditional Joins di SQL Server dan T-SQL Case Statement dalam JOIN ON Clause

misalnya

    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 

Sunting: Sesuai komentar.

Anda tidak dapat menentukan kondisi gabungan seperti yang Anda lakukan .. Periksa kueri di atas yang tidak memiliki kesalahan. Saya telah mengeluarkan kolom umum ke atas dan nilai kolom kanan akan dievaluasi dengan syarat.


1
apa conditional joinartinya Setiap bergabung (tidak termasuk salib) adalah persyaratan. Bagaimana kasus ini berbeda dari yang lain? Sampel Anda memiliki gabungan dengan kondisi, serta kueri OP telah bergabung dengan kondisi.
zerkms

@zerkms: Saya setuju, kedengarannya membingungkan. Saya percaya, gabungan kondisional dalam konteks ini berarti gabungan yang kondisinya tergantung pada kondisi lain.
Andriy M

@ Andriy M: ada alasan untuk memikirkan istilah lain untuk kondisi sepele OR?
zerkms

@zerkms: Er, ya, itu karena kedengarannya membingungkan. :) Tapi saya yakin Anda bermaksud bertanya apakah ada alasan untuk tidak memikirkan istilah lain, dalam hal ini saya tidak bisa memastikan. Jika Anda menanyakan alasan saya , yah, saya pikir saya tidak bisa cukup terganggu. :) Bagaimana dengan bergabung dengan kondisi alternatif ? Saya khawatir saya tidak pandai istilah coining. Perhatikan, meskipun, bahwa secara konseptual ini adalah tentang "kondisi kondisional", bukan tentang "kondisi dengan OR". Menggunakan ORhanyalah satu cara untuk mengimplementasikannya.
Andriy M

@ Andriy M: ok. Tetapi secara pribadi saya masih tidak melihat alasan untuk memberikan nama untuk kondisi sepele dengan 1 ORdan 2 ANDsatau dengan 1 CASE. Ini adalah kueri rutin yang tidak memiliki apa pun yang membedakannya dari yang lain.
zerkms

17

Coba ini:

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

Meskipun itu akan berhasil - kueri dalam pertanyaan terlihat sangat valid. Jadi masih tidak menjelaskan apa yang salah dengan kode OP
zerkms

10

Saya pikir Anda perlu dua pernyataan kasus:

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             

Hal ini karena:

  • pernyataan CASE mengembalikan nilai tunggal pada END
  • pernyataan ON membandingkan dua nilai
  • pernyataan CASE Anda sedang melakukan perbandingan di dalam pernyataan CASE. Saya akan menebak bahwa jika Anda menempatkan pernyataan KASUS Anda di SELECT Anda, Anda akan mendapatkan boolean '1' atau '0' yang menunjukkan apakah pernyataan KASUS dievaluasi menjadi Benar atau Salah

5

Saya mengambil contoh Anda dan mengeditnya:

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

Ya kamu bisa. Berikut ini sebuah contoh.

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
Meskipun kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan tentang bagaimana dan mengapa ini menyelesaikan masalah akan sangat membantu untuk meningkatkan kualitas posting Anda, dan mungkin menghasilkan lebih banyak suara. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, bukan hanya orang yang bertanya sekarang. Harap edit jawaban Anda untuk menambahkan penjelasan dan berikan indikasi tentang batasan dan asumsi apa yang berlaku.
bip ganda

0

Mengambil contoh DonkeyKong.

Masalahnya adalah saya perlu menggunakan variabel yang dideklarasikan. Ini memungkinkan untuk menyatakan sisi kiri dan kanan Anda tentang apa yang perlu Anda bandingkan. Ini untuk mendukung laporan SSRS di mana bidang yang berbeda harus ditautkan berdasarkan pilihan oleh pengguna.

Kasing awal menetapkan pilihan bidang berdasarkan pilihan dan kemudian saya dapat mengatur bidang yang harus saya cocokkan untuk bergabung.

Pernyataan kasus kedua dapat ditambahkan untuk sisi kanan jika variabel diperlukan untuk memilih dari bidang yang berbeda

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

Di sini saya telah membandingkan perbedaan dalam dua set hasil yang berbeda:

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 
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.