【问题标题】:How to do a count including not existing records?如何进行计数,包括不存在的记录?
【发布时间】:2015-03-18 05:14:26
【问题描述】:

如何对不存在的记录进行计数,计数应为“0”?

这是我的桌子:

CREATE TABLE SURVEY
(year CHAR(4),
cust CHAR(2));
INSERT INTO SURVEY VALUES ('2011', 'AZ');
INSERT INTO SURVEY VALUES ('2011', 'CO');
INSERT INTO SURVEY VALUES ('2012', 'ME'); 
INSERT INTO SURVEY VALUES ('2014', 'ME'); 
INSERT INTO SURVEY VALUES ('2014', 'CO');
INSERT INTO SURVEY VALUES ('2014', 'ME'); 
INSERT INTO SURVEY VALUES ('2014', 'CO');

我已经尝试过了,但它当然缺少零计数:

select cust, year, count(*) as count from SURVEY
group by cust, year

我想要这个结果:

+------+---------+--------+
| cust |    year |  count |
+------+---------+--------+
| AZ   |    2011 |  1     |
| AZ   |    2012 |  0     |
| AZ   |    2014 |  0     |
| CO   |    2011 |  1     |
| CO   |    2012 |  0     |
| CO   |    2014 |  2     |
| ME   |    2011 |  0     |
| ME   |    2012 |  1     |
| ME   |    2014 |  2     |
+------+---------+--------+

请注意:

  • 我的表有很多记录(~10k 不同的“客户”)
  • 年份可能不连续(例如跳过 2013 年)
  • 随着时间的推移,我可能会有 2015 年、2016 年等等
  • 实际查询将在 MS_ACCESS'2010 中执行(不确定是否重要)

请帮忙,谢谢!

【问题讨论】:

    标签: sql ms-access


    【解决方案1】:

    当不存在调查记录时,听起来您希望每个 cust x 年组合计数为零。如果是这种情况,您将需要另外两个表:客户和年份,然后执行以下操作:

        select leftside.cust, leftside.year, count(survey.cust) from
    (select * from customers, years) as leftside left join survey
    on leftside.cust = survey.cust and 
    leftside.year = survey.year 
    group by leftside.cust, leftside.year
    

    【讨论】:

    • sqlfiddle 很有帮助,修复并编辑了问题,现在似乎可以正常工作了
    • 是的,谢谢,它成功了。它也适用于 ms-access!
    【解决方案2】:
    select cust, year, (select count(cust) from survey) as count
      from SURVEY
    group by cust, year
    

    但是这个查询将返回所有记录的计数,没有分组条件。

    【讨论】:

    • 不是我想要的,需要正确计数。
    【解决方案3】:

    如果您有多年和客户的域表:

    select y.year, c.cust, count(s.year) as cnt
    from customer as c
    cross join year as y
    left join survey as s
        on s.year = y.year
        and s.cust = c.cust
    group by y.year, c.cust
    

    如果 ms-access 没有交叉连接,您可以这样做:

    from customer as c
    join year as y
        on 1 = 1
    

    如果您没有域表,您将需要以某种方式“发明”域,因为您无法从无到有。

    【讨论】:

    • 嗯,我弄错了 AZ 在 2012 年获得 1 个计数,应该为零,请参阅 sqlfiddle.com/#!6/bce5e/1
    • 哦,对不起。它应该是计数(s.year)。我会更新答案
    • sql 代码有效,但请您澄清 ms-access 代码。我收到错误,这是你的意思吗? select y.year, c.cust, count(s.year) as cnt from customer as c join year as y on 1 = 1 left join survey as s on s.year = y.year and s.cust = c.cust group by y.year, c.cust
    • 是的,我没有访问权限,所以我无法验证,但这是我的想法
    • stackoverflow.com/questions/29098795/join-clause-with-where/… 中,有人建议“访问需要在包含多个连接的任何查询的 FROM 子句中使用括号”
    【解决方案4】:

    如果您像其他人所说的那样拥有域表,那就太好了。如果您只需要依赖表中的数据,下面的查询将为您完成。

    select cp.cust, cp.year, iif(isnull(sum(cnt)), 0, sum(cnt)) as count from
    (select * from (
     (select distinct cust from survey) as c cross join
     (select distinct year from survey) as y)
    ) cp left join
    (select *, 1 as cnt from survey) s on cp.cust=s.cust and cp.year=s.year
    group by cp.cust, cp.year
    order by cp.cust,cp.year
    

    如果可行,您可以使用coalesce(sum(cnt),0) 而不是iif(isnull(sum(cnt)), 0, sum(cnt))。在 MS Access 中使用 iif 函数,在其他数据库中使用 coalesce

    【讨论】:

    • 我没有使用, 替换为cross join.. 现在它似乎工作sqlfiddle.com/#!6/eef78/7
    • 请检查之前评论中的 sqlfiddle 链接,看看是否有效。还是在 MS Access 中不起作用?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多