我对SQL还是很陌生,我创建的查询有一个小问题,我所做的是创建一个查询,该查询将创建我们所有员工在特定日期的时间记录的时间摘要。该查询有效,但是我需要做的是浏览所有用户的列表,而不仅仅是按当天记录时间的用户进行过滤。
SELECT
SUM(CASE WHEN TimeTransactions.ChargeBasis = 'C' THEN TimeTransactions.QuantityOfTime/60/6 ELSE 0 END) AS ChargableUnits,
SUM(CASE WHEN TimeTransactions.ChargeBasis = 'N' THEN TimeTransactions.QuantityOfTime/60/6 ELSE 0 END) AS NonChargableUnits,
SUM(CASE WHEN TimeTransactions.ChargeBasis = 'C' THEN TimeTransactions.ValueOfTime ELSE 0 END) AS ChargableValue,
SUM(CASE WHEN TimeTransactions.ChargeBasis = 'N' THEN TimeTransactions.ValueOfTime ELSE 0 END) AS NonChargableValue,
SUM(TimeTransactions.QuantityOfTime)/60/6 AS TotalUnits,
SUM(TimeTransactions.ValueOfTime) AS TotalValue,
Users.Code AS FeeEarner
FROM
Users INNER JOIN TimeTransactions ON TimeTransactions.FeeEarnerRef = Users.Code
WHERE
Users.FeeEarner = 1 AND Users.UserStatus = 0 AND
TimeTransactions.TransactionDate >= dateadd(day,datediff(day,1,GETDATE()),0)
AND TimeTransactions.TransactionDate < dateadd(day,datediff(day,0,GETDATE()),0)
GROUP BY
Users.Code
我希望它能将当天未进行时间记录的用户显示为每行显示“ NULL”,而不是将其从表中删除。
任何帮助或指导将不胜感激:)
答案 0 :(得分:1)
像这样的事情会做到的。
使用CTE建立您的用户查询并将您与用户相关的过滤条件放置在其中,然后将其加入您的时间表并在其中应用您的时间过滤条件。这样可以避免左连接原始的两个表,然后在右表上应用过滤器,以强制在内部进行内部连接。
编辑:
这是您要实现的目标的一个有效示例。我极大地简化了表结构,因为在提供的查询中引用的列与图像样本中提供的列不匹配。而且看起来查询正在尝试在where子句中使用列别名(在SQL Server中是不可能的)。
在下面的示例中,我在公共表表达式中对timetransaction表应用了过滤,然后将用户表加入到该表。这将产生以下输出。
对于时间不匹配过滤条件的用户,您会看到返回零,在这种情况下,使用内部联接根本不会返回这些用户。
有了更全面的数据示例(代表列结构和预期输出或类似的结果),我们可以找到一个更接近剪切和粘贴准备的解决方案,而此示例仅是一个示例,我将构造一个左联接,该联接的右侧表中需要进行过滤。
祝你好运,如果您有任何疑问,请告诉我。
declare @users table (
userid int identity(1,1),
username nvarchar(50)
);
declare @timetransaction table (
timetransactionid int identity(1,1),
userid int,
quantityoftime int
);
insert @users
values
('SomeBody'),
('AnyBody'),
('SomeoneElse');
insert @timetransaction
values
(1, 7),
(1, 12),
(2, 5),
(3, 71),
(3, 4);
declare @userid int = 1;
with timetransaction as (select userid, quantityoftime from @timetransaction where userid=1)
select u.userid, coalesce(SUM(quantityoftime), 0) as total from @users u
left join timetransaction t on u.userid=t.userid
group by u.userid;
用户表示例 enter image description here
时间交易表示例
enter image description here
答案 1 :(得分:1)
您应该使用LEFT JOIN
。但是正确设置过滤条件非常重要:
SELECT SUM(CASE WHEN tt.ChargeBasis = 'C' THEN tt.QuantityOfTime/60/6 ELSE 0 END) AS ChargableUnits,
SUM(CASE WHEN tt.ChargeBasis = 'N' THEN tt.QuantityOfTime/60/6 ELSE 0 END) AS NonChargableUnits,
SUM(CASE WHEN tt.ChargeBasis = 'C' THEN tt.ValueOfTime ELSE 0 END) AS ChargableValue,
SUM(CASE WHEN tt.ChargeBasis = 'N' THEN tt.ValueOfTime ELSE 0 END) AS NonChargableValue,
SUM(tt.QuantityOfTime)/60/6 AS TotalUnits,
SUM(tt.ValueOfTime) AS TotalValue,
u.Code AS FeeEarner
FROM Users u LEFT JOIN
TimeTransactions tt
ON tt.FeeEarnerRef = u.Code AND
tt.TransactionDate >= dateadd(day, -1, CONVERT(date, GETDATE())) AND
tt.TransactionDate < CONVERT(date, GETDATE())
WHERE u.FeeEarner = 1 AND u.UserStatus = 0
GROUP BY u.Code;
注意:
TimeTransactions
上的条件需要放在ON
子句中,而不是WHERE
中。DATE
数据类型。无需使用日期差来进行神秘计算即可从值中删除时间成分。