繁体   English   中英

如果不是所有行都存在,则来自不同表的 sql server 计数

[英]sql server count from different table if not all rows exists

我试图从 2 个表中获取结果。 第一个表是带有信息的 Id,来自第二个表,我想根据某些条件计算第一个表中每个 id 的存在。 这是我的代码:

SELECT p.stId, count(att.adate)
FROM payments p
LEFT JOIN Attendence att ON att.stId = p.stId
where p.cyear = 2018 and p.cmonth = 3 and p.cId = 10
and att.adate between '2018/03/01' and '2018/03/30 23:59:59.999' and att.cid 
= 10
GROUP BY p.stId

从第一个表(p)我有 3 个 ID。 但是当我运行它时它只返回 1 个 ID。 不存在于第二个表 (t) 中的 ids 它不会给出任何结果。 我想要做的是,如果第二个表中没有 id,我想为计数返回 0 (count(att.adate))

谢谢。

将右侧表条件从WHEREON以获得真正的left join结果:

SELECT p.stId, count(att.adate)
FROM payments p
LEFT JOIN Attendence att ON att.stId = p.stId
and att.adate between '2018/03/01' and '2018/03/30 23:59:59.999' and att.cid 
= 10
where p.cyear = 2018 and p.cmonth = 3 and p.cId = 10
GROUP BY p.stId

(在WHERE ,您会得到常规的inner join结果。)

您可能会遗漏结果,因为在您的 where 子句中,您对出勤表中的列有条件。 对于与付款表不匹配的情况,这些值将为 NULL。 所以我会让你的查询是这样的:

SELECT p.stId, count(att.adate)
FROM payments p
LEFT JOIN Attendence att ON att.stId = p.stId
where p.cyear = 2018 and p.cmonth = 3 and p.cId = 10
and (att.adate between '2018/03/01' and '2018/03/30 23:59:59.999' OR att.adate IS NULL) and (att.cid 
= 10 or att.cid IS NULL)
GROUP BY p.stId

您的问题是whereleft join变成了inner join 我还想简化日期算术:

SELECT p.stId, count(a.adate)
FROM payments p LEFT JOIN
     Attendence a
     ON a.stId = p.stId AND a.cid = p.cid AND 
        a.adate >= '2018-03-01' AND 
        a.adate < '2018-04-01
WHERE p.cyear = 2018 and p.cmonth = 3 and p.cId = 10
GROUP BY p.stId;

我做了什么改变:

  • 将第二个表上的过滤条件移至ON子句。 这就是LEFT JOIN的工作方式。
  • 我在cid上添加了一个JOIN条件,因此与10的比较只发生一次(在WHERE子句中)。
  • 将日期格式更改为 YYYY-MM-DD。 这与 ISO 8601 标准日期格式一致。
  • BETWEEN更改为>=< -- 当我在月份级别构建日期范围时,我只是不想考虑毫秒。

了解为什么不将BETWEEN与日期/时间一起使用的好地方是 Aaron Bertrand 的博客What do BETWEEN and the Devil Have In Common

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM