Tôi có thể sử dụng câu lệnh CASE trong điều kiện THAM GIA không?


140

Hình ảnh sau đây là một phần của Chế độ xem hệ thống Microsoft SQL Server 2008 R2. Từ hình ảnh chúng ta có thể thấy rằng mối quan hệ giữa sys.partitionssys.allocation_unitsphụ thuộc vào giá trị của sys.allocation_units.type. Vì vậy, để kết hợp chúng lại với nhau, tôi sẽ viết một cái gì đó tương tự như thế này:

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 

Nhưng mã trên cho một lỗi cú pháp. Tôi đoán đó là vì CASEtuyên bố. Bất cứ ai có thể giúp để giải thích một chút?


Thêm thông báo lỗi:

Msg 102, Cấp 15, Trạng thái 1, Dòng 6 Cú pháp không chính xác gần '='.

đây là hình ảnh


36
Bạn đã sử dụng phần mềm nào để tạo sơ đồ DB đẹp này?
Tìm hiểu

2
@LearnByRead bạn đã bao giờ tìm ra phần mềm nào được sử dụng chưa?
Người dùng632716

1
@ User632716 không tiếc là không!
LearnByRead

2
@ User632716 Mặc dù tôi thực sự nghĩ rằng đó là MySQL Workbench. Nhưng tôi chưa bao giờ nhận được phản hồi
LearnByRead

@LearnByRead Tôi không có ý kiến ​​gì. Nó được cung cấp bởi Microsoft.
Chỉ là người học

Câu trả lời:


222

Một CASEbiểu thức trả về một giá trị từ THENphần của mệnh đề. Bạn có thể sử dụng nó như vậy:

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

Lưu ý rằng bạn cần phải làm một cái gì đó với giá trị được trả về, ví dụ so sánh nó với 1. Câu lệnh của bạn đã cố gắng trả về giá trị của một phép gán hoặc kiểm tra tính bằng, không có nghĩa nào trong ngữ cảnh của mệnh đề CASE/ THEN. (Nếu BOOLEANlà kiểu dữ liệu thì kiểm tra tính bằng sẽ có ý nghĩa.)


@HABO cảm ơn vì điều đó đã làm việc cho tôi ... nhưng vấn đề là khi tôi làm điều này, điều kiện làm cho một sự sụp đổ ... xin vui lòng cho tôi biết làm thế nào để tôi phá vỡ nó?
Đèn chùm Sagar

1
@SagarTandel - Xin lỗi, tôi không hiểu "làm cho một cú ngã" và "làm thế nào để tôi phá vỡ nó". Bạn có thể làm rõ nhận xét của bạn? (Gần đây nổi lên từ một lần lặn ra khỏi Saba. Có thể là Nitrox.)
HABO

Nó kiểm tra tất cả các điều kiện mà tôi không muốn. Tôi muốn nó thoát khỏi trường hợp một khi nó phù hợp với một điều kiện.
Đèn chùm Sagar

3
@SagarTandel - Từ MSDN : "Câu lệnh CASE đánh giá các điều kiện của nó một cách tuần tự và dừng lại với điều kiện đầu tiên có điều kiện được thỏa mãn.". Nếu bạn muốn tất cả các hàng đã tham gia không khớp với bất kỳ điều kiện nào được nêu rõ ràng, chỉ cần thay đổi phần đuôi từ = 1sang = 0, nhưng tôi không nghĩ bạn sẽ thích kết quả đó.
HABO

THAM GIA sys.allocation_units MỘT TRƯỜNG HỢP TRÊN KHI bạn có thể viết nó trong khung Entity ở trên của giải pháp của bạn không
r.hamd

36

Thay vào đó, bạn chỉ cần THAM GIA vào cả hai bảng và trong mệnh đề SELECT của bạn, trả về dữ liệu từ bảng khớp với:

Tôi khuyên bạn nên truy cập liên kết này Tham gia có điều kiện trong SQL Server Tuyên bố trường hợp T-SQL trong Điều khoản THAM GIA

ví dụ

    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 

Chỉnh sửa: Theo nhận xét.

Bạn không thể chỉ định điều kiện tham gia như bạn đang làm .. Kiểm tra truy vấn ở trên không có lỗi. Tôi đã đưa ra cột chung và giá trị cột bên phải sẽ được đánh giá theo điều kiện.


1
những gì conditional joincó nghĩa là? Mỗi tham gia (không bao gồm chéo) là một điều kiện. Làm thế nào trường hợp này là khác nhau? Mẫu của bạn có kết nối bên trong với điều kiện, cũng như truy vấn OP đã tham gia với điều kiện.
zerkms

@zerkms: Tôi đồng ý, nghe có vẻ khó hiểu. Tôi tin rằng, một tham gia có điều kiện trong bối cảnh này có nghĩa là một tham gia có điều kiện phụ thuộc vào một điều kiện khác.
Andriy M

@Andriy M: bất kỳ lý do để nghĩ về một thuật ngữ khác cho điều kiện tầm thường với OR?
zerkms

@zerkms: Er, vâng, đó là vì nó nghe có vẻ khó hiểu. :) Nhưng tôi tin rằng bạn muốn hỏi nếu có bất kỳ lý do nào không nghĩ đến một thuật ngữ khác, trong trường hợp đó tôi không thể chắc chắn. Nếu bạn đang hỏi lý do của tôi , tốt, tôi nghĩ rằng tôi không thể bị làm phiền đủ. :) Làm thế nào về một tham gia với các điều kiện thay thế ? Tôi sợ rằng tôi không giỏi trong việc đặt điều khoản. Tuy nhiên, lưu ý rằng về mặt khái niệm, đây là về "điều kiện có điều kiện", chứ không phải về "điều kiện với OR". Sử dụng ORchỉ là một cách để thực hiện nó.
Andriy M

@Andriy M: ok. Nhưng cá nhân tôi vẫn không thấy lý do để đặt tên cho điều kiện tầm thường với 1 ORvà 2 ANDshoặc với 1 CASE. Đó là một truy vấn thông thường không có gì khác với nó.
zerkms

17

Thử cái này:

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

Mặc dù nó sẽ hoạt động - truy vấn trong câu hỏi trông hoàn toàn hợp lệ. Vì vậy, vẫn không giải thích điều gì sai với mã của OP
zerkms

10

Tôi nghĩ bạn cần hai báo cáo trường hợp:

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             

Điều này là do:

  • câu lệnh CASE trả về một giá trị duy nhất tại END
  • câu lệnh ON so sánh hai giá trị
  • câu lệnh CASE của bạn đang thực hiện so sánh bên trong câu lệnh CASE. Tôi đoán rằng nếu bạn đặt câu lệnh CASE của mình trong CHỌN, bạn sẽ nhận được boolean '1' hoặc '0' cho biết câu lệnh CASE được đánh giá là Đúng hay Sai

5

Tôi lấy ví dụ của bạn và chỉnh sửa nó:

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

Vâng, bạn có thể. Đây là một ví dụ.

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
Mặc dù mã này có thể giải quyết câu hỏi, bao gồm giải thích về cách thức và lý do giải quyết vấn đề này thực sự sẽ giúp cải thiện chất lượng bài đăng của bạn và có thể dẫn đến nhiều lượt bình chọn hơn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai, không chỉ người hỏi bây giờ. Vui lòng chỉnh sửa câu trả lời của bạn để thêm giải thích và đưa ra dấu hiệu về những hạn chế và giả định được áp dụng.
tiếng bíp đôi

0

Lấy ví dụ của DonkeyKong.

Vấn đề là tôi cần sử dụng một biến khai báo. Điều này cho phép nêu rõ bên trái và bên phải của bạn về những gì bạn cần so sánh. Đây là để hỗ trợ báo cáo SSRS trong đó các trường khác nhau phải được liên kết dựa trên lựa chọn của người dùng.

Trường hợp ban đầu đặt lựa chọn trường dựa trên lựa chọn và sau đó tôi có thể đặt trường tôi cần khớp để tham gia.

Một câu lệnh trường hợp thứ hai có thể được thêm vào cho phía bên tay phải nếu biến cần thiết để chọn từ các trường khác nhau

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

Ở đây tôi đã so sánh sự khác biệt trong hai bộ kết quả khác nhau:

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 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.