希望将多个JOIN优化为一个动态JOIN - 可能吗?

时间:2015-06-11 18:17:18

标签: sql tsql

所以我目前有一个查询,将买家和卖家名称拉入一个列值。我正在使用CASE声明,如果其中一个买方或卖方值为NULL,并且由于用户可以删除买方或卖方,并保留其原始Sequence值(1 ,2,3等等。)例如,假设我在BuyerSeller表中有以下条目:

OrdersID | Sequence | BuyerSellerType | FormalName
------------------------------------------------------
1        | 1        | 0               | Billy Bob
1        | 2        | 0               | Sally Sue
1        | 1        | 1               | Joe Dirt
1        | 3        | 1               | Dwayne Johnson

下面的SELECT语句将返回以下内容:

BuyerFormalName      | SellerFormalName
-----------------------------------------------
Billy Bob, Sally Sue | Joe Dirt, Dwayne Johnson

这是声明。现在,我只是想看看是否有任何方法可以动态或更轻松地生成相同的结果,而不需要这么多JOINs?我得到了我想要的结果,但我希望能够调整我的技能和知识,特别是因为我可能需要增加> 3以上JOINs。任何见解都会非常感激!

SELECT
    CASE
        WHEN ISNULL(B.FormalName,'') <> '' AND ISNULL(B2.FormalName,'') <> '' AND ISNULL(B3.FormalName,'') <> ''
            THEN B.FormalName + ', ' + B2.FormalName + ', ' + B3.FormalName
        WHEN ISNULL(B.FormalName,'') <> '' AND ISNULL(B2.FormalName,'') = '' AND ISNULL(B3.FormalName,'') <> ''
            THEN B.FormalName + ', ' + B3.FormalName
        WHEN ISNULL(B.FormalName,'') <> '' AND ISNULL(B2.FormalName,'') <> '' AND ISNULL(B3.FormalName,'') = ''
            THEN B.FormalName + ', ' + B2.FormalName
        WHEN ISNULL(B.FormalName,'') = '' AND ISNULL(B2.FormalName,'') <> '' AND ISNULL(B3.FormalName,'') <> ''
            THEN B2.FormalName + ', ' + B3.FormalName
        WHEN ISNULL(B.FormalName,'') = '' AND ISNULL(B2.FormalName,'') <> '' AND ISNULL(B3.FormalName,'') = ''
            THEN B2.FormalName
        WHEN ISNULL(B.FormalName,'') = '' AND ISNULL(B2.FormalName,'') = '' AND ISNULL(B3.FormalName,'') <> ''
            THEN B3.FormalName
        ELSE B.FormalName
    END AS 'BuyerFormalName'
    ,CASE
        WHEN ISNULL(S.FormalName,'') <> '' AND ISNULL(S2.FormalName,'') <> '' AND ISNULL(S3.FormalName,'') <> ''
            THEN S.FormalName + ', ' + S2.FormalName + ', ' + S3.FormalName
        WHEN ISNULL(S.FormalName,'') <> '' AND ISNULL(S2.FormalName,'') = '' AND ISNULL(S3.FormalName,'') <> ''
            THEN S.FormalName + ', ' + S3.FormalName
        WHEN ISNULL(S.FormalName,'') <> '' AND ISNULL(S2.FormalName,'') <> '' AND ISNULL(S3.FormalName,'') = ''
            THEN S.FormalName + ', ' + S2.FormalName
        WHEN ISNULL(S.FormalName,'') = '' AND ISNULL(S2.FormalName,'') <> '' AND ISNULL(S3.FormalName,'') <> ''
            THEN S2.FormalName + ', ' + S3.FormalName
        WHEN ISNULL(S.FormalName,'') = '' AND ISNULL(S2.FormalName,'') <> '' AND ISNULL(S3.FormalName,'') = ''
            THEN S2.FormalName
        WHEN ISNULL(S.FormalName,'') = '' AND ISNULL(S2.FormalName,'') = '' AND ISNULL(S3.FormalName,'') <> ''
            THEN S3.FormalName
        ELSE S.FormalName
    END AS 'SellerFormalName'
FROM
    Checks C
    LEFT JOIN BuyerSeller B
        ON C.OrdersID = B.OrdersID
        AND B.Sequence = 1
        AND B.BuyerSellerType = 0
    LEFT JOIN BuyerSeller B2
        ON C.OrdersID = B2.OrdersID
        AND B2.Sequence = 2
        AND B2.BuyerSellerType = 0
    LEFT JOIN BuyerSeller B3
        ON C.OrdersID = B3.OrdersID
        AND B3.Sequence = 3
        AND B3.BuyerSellerType = 0
    LEFT JOIN BuyerSeller S
        ON C.OrdersID = S.OrdersID
        AND S.Sequence = 1
        AND S.BuyerSellerType = 1
    LEFT JOIN BuyerSeller S2
        ON C.OrdersID = S2.OrdersID
        AND S2.Sequence = 2
        AND S2.BuyerSellerType = 1
    LEFT JOIN BuyerSeller S3
        ON C.OrdersID = S3.OrdersID
        AND S3.Sequence = 3
        AND S3.BuyerSellerType = 1

2 个答案:

答案 0 :(得分:2)

你在找这样的东西吗?

WITH BuyerSeller
AS
(
    SELECT *
    FROM
    (
        VALUES  (1,1,0,'Billy Bob'),
                (1,2,0,'Sally Sue'),
                (1,1,1,'Joe Dirt'),
                (1,3,1,'Dwayne Johnson')
    ) A(OrdersID,[Sequence],BuyerSellerType,FormalName)
)

SELECT DISTINCT OrdersID,
                STUFF(Bname,1,2,'') AS BuyerFormalName,             
                STUFF(Sname,1,2,'') AS SellerFormalName
FROM BuyerSeller A
CROSS APPLY (
                SELECT ', ' + FormalName
                FROM BuyerSeller B
                WHERE       A.OrdersID = B.OrdersID
                        AND BuyerSellerType = 0
                ORDER BY [Sequence]
                FOR XML PATH('')
            ) CA(Bname)
CROSS APPLY (
                SELECT ', ' + FormalName
                FROM BuyerSeller B
                WHERE       A.OrdersID = B.OrdersID
                        AND BuyerSellerType = 1
                ORDER BY [Sequence]
                FOR XML PATH('')
            ) CA2(Sname)

结果:

OrdersID    BuyerFormalName        SellerFormalName
----------- ---------------------  -----------------------
1           Billy Bob, Sally Sue   Joe Dirt, Dwayne Johnson             

答案 1 :(得分:0)

如果行/值的数量已知(和小),我仍然更喜欢旧式的MAX / CASE:

SELECT
   c.OrdersID,
   BuyerFormalName,
   SellerFormalName
FROM Checks C
LEFT JOIN
 (
   SELECT
      OrdersID,
      STUFF(MAX(CASE WHEN Sequence = 1 AND BuyerSellerType = 0 THEN ', ' + FormalName ELSE '' end) +
            MAX(CASE WHEN Sequence = 2 AND BuyerSellerType = 0 THEN ', ' + FormalName ELSE '' end) +
            MAX(CASE WHEN Sequence = 3 AND BuyerSellerType = 0 THEN ', ' + FormalName ELSE '' end), 1,2,'') AS BuyerFormalName,
      STUFF(MAX(CASE WHEN Sequence = 1 AND BuyerSellerType = 1 THEN ', ' + FormalName ELSE '' end) +
            MAX(CASE WHEN Sequence = 2 AND BuyerSellerType = 1 THEN ', ' + FormalName ELSE '' end) +
            MAX(CASE WHEN Sequence = 3 AND BuyerSellerType = 1 THEN ', ' + FormalName ELSE '' end), 1,2,'') AS SellerFormalName
   FROM BuyerSeller
   GROUP BY OrdersID
 ) AS b
ON C.OrdersID = B.OrdersID
;