SQL查询以显示具有空值的用户

时间:2019-06-19 09:32:17

标签: sql sql-server

我对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”,而不是将其从表中删除。

任何帮助或指导将不胜感激:)

2 个答案:

答案 0 :(得分:1)

像这样的事情会做到的。

使用CTE建立您的用户查询并将您与用户相关的过滤条件放置在其中,然后将其加入您的时间表并在其中应用您的时间过滤条件。这样可以避免左连接原始的两个表,然后在右表上应用过滤器,以强制在内部进行内部连接。

编辑:

这是您要实现的目标的一个有效示例。我极大地简化了表结构,因为在提供的查询中引用的列与图像样本中提供的列不匹配。而且看起来查询正在尝试在where子句中使用列别名(在SQL Server中是不可能的)。

在下面的示例中,我在公共表表达式中对timetransaction表应用了过滤,然后将用户表加入到该表。这将产生以下输出。

enter image description here

对于时间不匹配过滤条件的用户,您会看到返回零,在这种情况下,使用内部联接根本不会返回这些用户。

有了更全面的数据示例(代表列结构和预期输出或类似的结果),我们可以找到一个更接近剪切和粘贴准备的解决方案,而此示例仅是一个示例,我将构造一个左联接,该联接的右侧表中需要进行过滤。

祝你好运,如果您有任何疑问,请告诉我。

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中。
  • SQL Server支持DATE数据类型。无需使用日期差来进行神秘计算即可从值中删除时间成分。
  • 表别名使查询更易于编写和阅读。