这个问题的基本概念是我需要一个查询,它为我提供了一个独特的用户列表和我们正在寻找违规的日期。它显示了日期和用户,无论是否存在违规行为。日期表外部适用于用户始终显示用户的所有日期以及他们是否在该日期有违规。 例如:
UserID Date IsViolation
1 1/1 Y
1 1/2 Y
1 1/3 N
2 1/1 N
2 1/2 N
2 1/3 N
问题是我需要加入几个表来为这些用户产生违规行为。所以到目前为止看起来像这样:
SELECT u.ID AS UserID,
u.FirstName,
u.LastName,
uc.ClientName,
ul.LocationName,
d.Date
FROM dbo.User AS u
JOIN dbo.UserClient AS uc ON u.ID = uc.UserID
JOIN dbo.UserLocation AS ul ON u.ID = ul.userID
OUTER APPLY #Dates
LEFT JOIN (
SELECT uv.UserID,
uv.ViolationID,
uv.ViolationDate,
v.ViolationName,
vm.ViolationTypeID,
uv.Date
FROM dbo.UserViolation AS uv
JOIN dbo.Violation AS v ON uv.ViolationID = v.ID
JOIN dbo.ViolationMeta AS vm ON vm.ViolationID = v.ID
) AS v ON v.UserID = u.ID
AND v.Date = d.Date
现在我将列出每个日期和用户的违规列表,如下所示:
UserID Date ViolationTypeID
1 1/1 1
1 1/1 2
1 1/1 3
1 1/2 NULL
1 1/3 1
2 1/1 NULL
etc....
我需要根据ViolationTypeID和ViolationID将这些分组到特定的存储桶中。所以我想的是在同一个查询中做类似下面的事情:
SELECT u.ID AS UserID,
u.FirstName,
u.LastName,
uc.ClientName,
ul.LocationName,
d.Date,
MAX(CASE WHEN v.ViolationID IN (1,2,3) AND [ViolationTypeID] = 1 THEN 1 ELSE 0 END) AS [FormViolation]
MAX(CASE WHEN v.ViolationTypeID IN (5,6,7) THEN 1 ELSE 0 END) AS [UrgentViolaion]
MIN(CASE WHEN v.ID IS NOT NULL AND v.ViolationTypeID IN (1,2,3) THEN 0 ELSE 1 END) AS [NoViolation]
etc.....
GROUP BY u.ID,
u.FirstName,
u.LastName,
uc.ClientName,
ul.LocationName,
d.Date
我试图点击表格只产生一次违规,而不是在表格的单独连接中为每个单独的场景命中它们。这对我来说似乎有点复杂,是否有更简单/更有效的方法来实现这一目标?
答案 0 :(得分:0)
据我所知,您需要cross join
来获取用户和日期。然后是left join
违规和聚合。这有点复杂,因为违规日期是violations
而不是userviolations
(这对我来说真的没有意义),但是:
select u.id, d.date,
(case when max(v.date) is null then 'N' else 'Y' end) as IsViolation
from dbo.User u cross join
#dates d left join
dbo.userviolation uv
on u.id = uv.userid and
d.date = uv.date
group by u.id, d.date;