T-SQL Удаление нескольких левое соединение - PullRequest
0 голосов
/ 07 октября 2011

У меня есть такой запрос. Он возвращает ColA и ColB из TableA и UserName из таблицы Users. Затем он отображает несколько полей из таблицы B в качестве дополнительных столбцов к результатам. Это работает, но есть ли лучший способ, чем использовать эти несколько левых соединений?

SELECT a.COlA, a.ColB, u.UserName,
b1.Value,
b2.Value,
b3.Value,
b4.Value,

FROM TableA a JOIN Users u ON a.UserId = u.UserId
    LEFT JOIN TableB b1 ON a.EventId = b1.EventId AND b1.Code = 5
    LEFT JOIN TableB b2 ON a.EventId = b2.EventId AND b2.Code = 15
    LEFT JOIN TableB b3 ON a.EventId = b3.EventId AND b3.Code = 18
    LEFT JOIN TableB b4 ON a.EventId = b4.EventId AND b4.Code = 40

WHERE (a.UserId = 3) ORDER BY u.UserName ASC

Таблица B выглядит следующим образом:

Id | EventId | Code | Value
----------------------------
1  |    1    |  5   | textA
2  |    1    |  15  | textB
3  |    1    |  18  | textC

Иногда код отсутствует, но для каждого события нет дублирующихся кодов (поэтому каждое LEFT JOIN - это просто другая ячейка в той же записи результата).

Ответы [ 3 ]

1 голос
/ 07 октября 2011
SELECT 
  a.COlA, a.ColB, u.UserName
  ,MAX(CASE WHEN b.Value = 5 THEN b.value ELSE 0 END) AS V5
  ,MAX(CASE WHEN b.Value = 15 THEN b.value ELSE 0 END) AS V15 
  ,MAX(CASE WHEN b.Value = 18 THEN b.value ELSE 0 END) AS V18 
  ,MAX(CASE WHEN b.Value = 40 THEN b.value ELSE 0 END) AS V45 
  ,COUNT(CASE WHEN b.Value not IN (5,15,18,40) THEN 1 ELSE NULL END) AS CountVOther
FROM TableA a 
INNER JOIN Users u ON a.UserId = u.UserId
LEFT  JOIN TableB b ON (a.EventId = b.EventId)
WHERE (a.UserId = 3) 
GROUP BY a.colA, a.colB, u.Username
ORDER BY u.UserName ASC
1 голос
/ 07 октября 2011

Я не могу понять, почему вы хотите изменить что-то, что работает, но вот другой способ (который объединяет эти LEFT, но по-другому):

SELECT a.COlA, a.ColB, u.UserName,
  ( SELECT b.Value FROM TableB b WHERE a.EventId = b.EventId AND b.Code = 5 ),
  ( SELECT b.Value FROM TableB b WHERE a.EventId = b.EventId AND b.Code = 15 ),
  ( SELECT b.Value FROM TableB b WHERE a.EventId = b.EventId AND b.Code = 18 ),
  ( SELECT b.Value FROM TableB b WHERE a.EventId = b.EventId AND b.Code = 40 )

FROM TableA a JOIN Users u ON a.UserId = u.UserId

WHERE (a.UserId = 3) 

ORDER BY u.UserName ASC
1 голос
/ 07 октября 2011

Если у вас есть только одна строка TableB для каждых EventID и (Code=5 или Code=15 или Code=18 или Code=40), то вы можете проверить этот запрос:

;WITH SourceCTE
AS
(
    SELECT a.COlA, a.ColB, u.UserName, b.Code, b.Value
    FROM TableA a JOIN Users u ON a.UserId = u.UserId
    INNER /*or LEFT OUTER*/ JOIN TableB b ON a.EventId = b1.EventId AND b.Code IN (5,15,18,40)
    WHERE (a.UserId = 3) ORDER BY u.UserName ASC
)
SELECT  pvt.CodA, pvt.ColB, pvt.UserName
    ,pvt.[5]  AS b1Value
    ,pvt.[15] AS b2Value
    ,pvt.[18] AS b3Value
    ,pvt.[40] AS b4Value
FROM    SourceCTE src
PIVOT   (MAX(src.Value) FOR src.Code IN ([5],[15],[18],[40])) pvt;

Примечание: если у вас SQL Server 2008, вы можете создать уникальный отфильтрованный индекс для EventID, включая поле Value с одним фильтром: WHERE Code IN (5,15,18,40).

...