SQL SUM与CASE和DISTINCT?

时间:2010-10-14 17:47:48

标签: sql postgresql

继续我的last question ...

  

让我试着解释一下我的架构。我有三个表,我们将调用用户(具有列id和名称),party(具有列id,partydate和user_id)和问题(具有列id,createdate和user_id)。我的要求是向每个用户展示去年的参与人数和去年创建的问题。

我的查询如下:

SELECT users.id, users.name,  
  SUM(CASE WHEN (parties.party> NOW() - interval '1 year') THEN 1 ELSE 0 END) 
    AS numparties, 
  SUM(CASE WHEN (questions.createdate> NOW() - interval '1 year') THEN 1 ELSE 0 END)
    AS numquestions
FROM users
  LEFT JOIN parties ON users.id=parties.user_id
  LEFT JOIN questions ON users.id=questions.user_id
GROUP BY users.id, users.name;

这几乎是100%。我收到了所有存在的用户的结果。问题是,对于一些用户(非常少的用户),我正在计算一次聚会或问题两次。例如,如果我将上面的查询更改为仅显示parties.id和questions.id而不是将它们相加并删除GROUP BY,我可能会得到类似的结果:

user.id | user.name | parties.id | questions.id  
-----------------------------------------------
0          John          15             2
0          John          15             7

你可以看到它显示了parties.id两次。

当我使用COUNT()时,我可以依赖DISTINCT,但是使用SUM,我不知道怎么做。我想要这样的东西:

SUM(CASE WHEN (parties.party> NOW() - interval '1 year' AND parties.id IS DISTINCT) THEN 1 ELSE 0 END) 
AS numparties, 

但当然这是无效的。这个小问题可以轻易纠正吗?

2 个答案:

答案 0 :(得分:3)

我不会为你编写代码(因为它是家庭作业),但你会想把这两个计算放到子查询中。

这是一个模板:

  SELECT users.id, users.name, 
         subquery1.result_of_calculation1, subquery2.result_of_calculation2
    FROM users
         LEFT JOIN (
            --calculation 1
         ) subquery1
         ON users.id = subquery1.user_id
         LEFT JOIN (
            --calculation 2
         ) subquery2
         ON users.id = subquery2.user_id
GROUP BY users.id, users.name;

答案 1 :(得分:0)

按照亚当的提示,我想出了这个:

SELECT users.id, users.name, 
  COALESCE(tparties.ecount,0),
  COALESCE(tquestions.pcount,0)
FROM users
  FULL JOIN (
    SELECT user_id,COUNT(parties.id) AS ecount 
    FROM parties 
    JOIN users ON parties.user_id = users.id 
      AND parties.partydate > NOW() - interval '1 year' 
    GROUP BY user_id) 
    as tparties ON users.id=tparties.user_id
  FULL JOIN (
    SELECT user_id,COUNT(questions.id) AS pcount 
    FROM questions JOIN users ON questions.user_id = users.id 
      AND questions.createdate > NOW() - interval '1 year' 
    GROUP BY user_id) 
    as tquestions ON users.id=tquestions.user_id
;

好消息是列出了所有用户并且所有计数都是正确的。坏消息是它按user_id排序日期,而老师给出的检查我​​们的查询的结果似乎是无序的。我认为这意味着上述查询不是老师正在寻找的答案。但是,结果是一样的,考虑到我在一个问题上投入的时间,这对我来说已经足够了。谢谢您的帮助。