好的,所以我遇到了一个严重的问题
我有原始查询(在下面这一个中是查询A)从SiteAppointmentArrivals
中选择所有信息(包括空),这很棒 - 因为我需要显示用户何时没有到达指定站点- 缺席。
但是,这些网站都分组在不同的组中。因此,一个组可能有五个站点,另一个组可能只有一个,等等。有时当用户登录到一个分组站点时,他们只会登录到一个站点 - 逻辑上他们应该登录到所有站点 - 但是在系统中它目前显示他们已登录到一个站点,其他站点为NULL。
现在,我只想在每个组中选择一个站点(因此max(s.siteid)
适用于登录所有站点或根本不显示任何站点的人员。但是,对于那些奇怪的人,他们有到达日期和空值 - 两行显示。我想消除此实例中的NULL行,因为他们通过登录其中一个站点逻辑登录到该组。
我创建了这个伪代码 - 尝试组合查询的两个版本 - 一个包含所有信息,另一个包含只有到达人员的信息。
如果在B中找到来自A(所有信息)的GroupID(仅到达信息),则显示B行信息,如果A中的GroupID不在B中,则显示A行。我认为逻辑会适当地捕获我需要的东西,但我不知道如何在SQL中表达它
编辑简洁
Select DISTINCT
CASE WHEN a.GroupID=b.GroupID THEN b.*
WHEN a.GroupID <> b.GroupID THEN a.* END -- Psuedo Code
From
(SELECT DISTINCT
max(s.SiteID) SiteID,
s.GroupID,
saa.Time ArrivalTime,
sas.ScannerUserID
FROM
dbo.Sites s
INNER JOIN dbo.SiteAppointments sa ON s.SiteID = sa.SiteID
INNER JOIN dbo.SiteAppointmentsScanners sas ON sa.SiteAppointmentID = sas.SiteAppointmentID
LEFT JOIN dbo.SiteAppointmentArrivals saa ON sa.SiteAppointmentID = saa.SiteAppointmentId
AND saa.ScannerUserID = sas.ScannerUserID
WHERE
ProjectID = 110
AND
(
(CAST(sa.StartDateTime AS DATE) >= '09/03/2014' AND CAST(sa.StartDateTime AS DATE) <= '09/03/2014')
OR
(CAST(sa.EndDateTime AS DATE) >= '09/03/2014' AND CAST(sa.EndDateTime AS DATE) <= '09/03/2014')
)
AND ((CAST(saa.Date AS DATE) >= '09/03/2014' AND CAST(saa.Date AS DATE) <= '09/03/2014') OR saa.Date IS NULL)
GROUP BY
s.GroupID,
saa.Time,
sas.ScannerUserID
)a
LEFT JOIN
(SELECT DISTINCT
max(s.SiteID) SiteID,
s.GroupID,
saa.Time ArrivalTime,
sas.ScannerUserID
FROM
dbo.Sites s
INNER JOIN dbo.SiteAppointments sa ON s.SiteID = sa.SiteID
INNER JOIN dbo.SiteAppointmentsScanners sas ON sa.SiteAppointmentID = sas.SiteAppointmentID
INNER JOIN dbo.SiteAppointmentArrivals saa ON sa.SiteAppointmentID = saa.SiteAppointmentId
AND saa.ScannerUserID = sas.ScannerUserID
WHERE
ProjectID = 110
AND
(
(CAST(sa.StartDateTime AS DATE) >= '09/03/2014' AND CAST(sa.StartDateTime AS DATE) <= '09/03/2014')
OR
(CAST(sa.EndDateTime AS DATE) >= '09/03/2014' AND CAST(sa.EndDateTime AS DATE) <= '09/03/2014')
)
AND ((CAST(saa.Date AS DATE) >= '09/03/2014' AND CAST(saa.Date AS DATE) <= '09/03/2014') OR saa.Date IS NULL)
GROUP BY
s.GroupID,
saa.Time,
sas.ScannerUserID
) b ON a.SiteID=b.SiteID
一个例子:
SiteID | GroupID | ArrivalTime | Scanner
------------------------------------------------------
12345 | 54321 | NULL | 1011
------------------------------------------------------
67890 | 54321 | 2014-09-03 09:09:48.053 | 1011
所以这里 - 扫描器/用户已进入组内的站点(所以从技术上讲,即使其他站点为NULL,他也已登录到组中)所以我想隐藏NULL值并保持到达值。
答案 0 :(得分:2)
我认为您需要使用ROW_NUMBER()排名功能:
WITH SiteArrivals AS (
SELECT DISTINCT
s.SiteID,
s.GroupID,
saa.Time ArrivalTime,
sas.ScannerUserID,
ROW_NUMBER() OVER (PARTITION BY s.GroupID ORDER BY saa.Time DESC, s.SiteID DESC) rn
FROM
dbo.Sites s
INNER JOIN dbo.SiteAppointments sa ON s.SiteID = sa.SiteID
INNER JOIN dbo.SiteAppointmentsScanners sas ON sa.SiteAppointmentID = sas.SiteAppointmentID
LEFT JOIN dbo.SiteAppointmentArrivals saa ON sa.SiteAppointmentID = saa.SiteAppointmentId
AND saa.ScannerUserID = sas.ScannerUserID )
SELECT *
FROM SiteArrivals sa WHERE SiteID IS NOT NULL and rn = 1
这是一个演示此解决方案的SqlFiddle - http://sqlfiddle.com/#!3/b57c6/4
答案 1 :(得分:0)
如果我正确理解了这个问题,你只需要复制&#34;到达那些行的到达时间,其中Scanner / user相同且GroupID相同,但SiteID不同且未指定ArrivalTime。
在这种情况下,您只需使用以下查询:
;
with f1 as
(
SELECT DISTINCT
max(s.SiteID) SiteID,
s.GroupID,
saa.Time ArrivalTime,
sas.ScannerUserID
FROM dbo.Sites s
INNER JOIN dbo.SiteAppointments sa
ON s.SiteID = sa.SiteID
INNER JOIN dbo.SiteAppointmentsScanners sas
ON sa.SiteAppointmentID = sas.SiteAppointmentID
LEFT JOIN dbo.SiteAppointmentArrivals saa
ON sa.SiteAppointmentID = saa.SiteAppointmentId
AND saa.ScannerUserID = sas.ScannerUserID
WHERE
ProjectID = 110
AND
(
(CAST(sa.StartDateTime AS DATE) >= '09/03/2014' AND CAST(sa.StartDateTime AS DATE) <= '09/03/2014')
OR
(CAST(sa.EndDateTime AS DATE) >= '09/03/2014' AND CAST(sa.EndDateTime AS DATE) <= '09/03/2014')
)
AND ((CAST(saa.Date AS DATE) >= '09/03/2014' AND CAST(saa.Date AS DATE) <= '09/03/2014') OR saa.Date IS NULL)
GROUP BY
s.GroupID,
saa.Time,
sas.ScannerUserID
),
f2 as
(
select GroupID, ScannerUserID, max(ArrivalTime) ArrivalTime
from f1
group by GroupID, ScannerUserID
)
select f1.SiteID, f1.GroupID, f2.ArrivalTime, f1.ScannerUserID
from f1 f1
left join f2 f2
on f1.GroupID = f2.GroupID
and f1.ScannerUserID = f2.ScannerUserID
可以在此处找到演示此解决方案的SqlFiddle:http://sqlfiddle.com/#!3/623b2c/10