MySQL:计算多个表中的重复行而不会出现计数

时间:2016-04-05 20:01:30

标签: mysql count

我试图计算表格中每个人完成的事件数量。我遇到的问题是人们在我的人员表中有多个工作,这意味着每个人都有目的多行 - 当我尝试计算时,这会使我的事件表加倍。

这是我的代码的 SQL Fiddle 。最容易看到ID#1只有两个事件已完成,但表计数四个,因为它们也有两个工作。

这是我的示例架构:

CREATE TABLE persontable
(id INT NOT NULL
, name VARCHAR(255) NOT NULL
, employer VARCHAR(255) NOT NULL
, PRIMARY KEY(id,employer)
);

CREATE TABLE eventtable
(id INT NOT NULL 
, name VARCHAR(255) NOT NULL
, eventname VARCHAR(255) NOT NULL
, eventdate DATE NOT NULL
, status VARCHAR(255) NOT NULL
, PRIMARY KEY (id,eventname,eventdate));

INSERT INTO persontable (id,name,employer) VALUES
(1,"Joe","Party Inc."),
(1,"Joe","Body Shop"),
(2,"Puddy","Body Shop"),
(3,"Newman","Postal Service"),
(3,"Newman","Computers Inc."),
(4,"Delores","Mulva LLC"),
(5,"Morty","Executive Raincoats"),
(6,"Helen","Body Shop"),
(7,"Frank","Retired"),
(7,"Frank","Mulva LLC"),
(8,"Estelle","Retired"),
(9,"Mandelbaum","Weight Lifters Guild"),
(9,"Mandelbaum","The Wiz"),
(10,"Fred","The Wiz");

INSERT INTO eventtable (id,name,eventname,eventdate,status) VALUES
(1,"Joe","Mayo Party",5/4/94,"Completed"),
(1,"Joe","Coat Shopping",1/2/95,"Completed"),
(4,"Delores","Play",5/9/94,"Completed"),
(4,"Delores","Name Guessing",3/9/98,"Completed"),
(9,"Mandelbaum","Working Out",3/2/97,"Declined"),
(10,"Fred","Store Sale",8/9/96,"Completed");

我的相当简单的查询是添加额外的计数:

SELECT
  p.id,
  e.id,
  COUNT(DISTINCT CASE WHEN e.status="Completed" THEN e.id ELSE NULL END) AS EVENT,
  COUNT(CASE WHEN e.status="Completed" THEN e.id ELSE NULL END) AS YTDAllShiftsComp
    FROM persontable p
    LEFT JOIN eventtable e ON p.id = e.id
    GROUP BY p.id;

我希望样本的结果是:

id  id      EVENT   YTDAllShiftsComp
1   1       1       2
2   (null)  0       0
3   (null)  0       0
4   4       1       2
5   (null)  0       0
6   (null)  0       0
7   (null)  0       0
8   (null)  0       0
9   9       0       0
10  10      1       1

感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

您可以使用相关子查询:

SELECT
  p.id,
  (SELECT COUNT(DISTINCT CASE WHEN e.status="Completed" THEN e.id END) 
  FROM eventtable e
  WHERE p.id = e.id) AS EVENT,
  (SELECT COUNT(CASE WHEN e.status="Completed" THEN e.id END) 
   FROM eventtable e
   WHERE p.id = e.id) AS YTDAllShiftsComp
FROM persontable p    
GROUP BY p.id;

Demo here

答案 1 :(得分:1)

当你没有规范化你的数据时会发生什么。既然每个人都可以参加多个活动而且每个活动都可以容纳多个人,你需要一个中间表来保存两个表的主键,这被称为多对多关系。所以我加入了不同的人ID,消除了重复,但真正的解决方案是添加一个新表。

SELECT
  x.id,
  e.id,
  COUNT(DISTINCT CASE WHEN e.status="Completed" THEN e.id ELSE NULL END) AS EVENT,
  COUNT(CASE WHEN e.status="Completed" THEN e.id ELSE NULL END) AS YTDAllShiftsComp
    FROM (SELECT id FROM persontable GROUP BY id)x
    LEFT JOIN eventtable e ON x.id = e.id
    GROUP BY x.id;

答案 2 :(得分:0)

正如Georgios所提到的,你需要子查询 - 但是如果确实需要那个有时为空的第二个ID列,那么如果事件计数为零,你将需要将主语句包装成NULL。

SELECT id, if(event=0, NULL, event) as idagain, event, ytdallshiftscomp
  FROM (SELECT distinct p.id,
               (SELECT count(distinct id) FROM eventtable WHERE id=p.id AND status="Completed") AS EVENT,
               (SELECT count(*) FROM eventtable WHERE id=p.id AND status="Completed") AS ytdallshiftscomp
          FROM persontable p) q