【问题标题】:Postgres COUNT number of column values with INNER JOINPostgres COUNT 个带有 INNER JOIN 的列值
【发布时间】:2015-10-09 11:29:33
【问题描述】:

我正在 Postgres 9.3 中创建报告。这是我的SQL Fiddle
基本上我有两张表,responsesquestions,结构是:

responses
->id
->question_id
->response

questions
->id
->question
->costperlead

response 列只能有 3 个值,Yes/No/Possbily, 我的报告应该有以下列:

  question_id
, # of Yes Responses
, # of No Responses
, # of Possbily Responses
, Revenue

然后:

# of Yes Responses - count of all Yes values in the response column
# of No Responses - count of all No values in the response column
# of Possbily Responses - count of all 'Possbily' values in the response column

收入是costperlead *(是响应的数量 + 可能响应的数量)。

我不知道如何构建查询,我是新来的,而且我来自 MySQL,所以对于 postgres,有些事情是不同的。在我的 SQL Fiddle 示例中,大多数响应是 Yes 和 Null,最终没关系,会有可能和 No。

到目前为止,我只有:

SELECT a.question_id
FROM responses a
INNER JOIN questions b ON a.question_id = b.id
WHERE a.created_at = '2015-07-17'
GROUP BY a.question_id;

【问题讨论】:

    标签: database postgresql count inner-join aggregate-filter


    【解决方案1】:

    由于唯一的谓词过滤表 responses 中的行,因此首先聚合响应,然后加入问题是最有效的:

    SELECT *, q.costperlead * (r.ct_yes + r.ct_maybe) AS revenue
    FROM  (
       SELECT question_id
            , count(*) FILTER (WHERE response = 'Yes')      AS ct_yes
            , count(*) FILTER (WHERE response = 'No')       AS ct_no
            , count(*) FILTER (WHERE response = 'Possibly') AS ct_maybe
       FROM   responses
       WHERE  created_at = '2015-07-17'
       GROUP  BY 1
       ) r
    JOIN   questions q ON q.id = r.question_id;
    

    db小提琴here

    这使用聚合 FILTER 子句(在 Postgres 9.4 或更高版本中)。见:

    另外:考虑将response 实现为boolean 类型和true/false/null

    对于 Postgres 9.3

    SELECT *, q.costperlead * (r.ct_yes + r.ct_maybe) AS revenue
    FROM  (
       SELECT question_id
            , count(response = 'Yes' OR NULL)      AS ct_yes
            , count(response = 'No' OR NULL)       AS ct_no
            , count(response = 'Possibly' OR NULL) AS ct_maybe
       FROM   responses
       WHERE  created_at = '2015-07-17'
       GROUP  BY 1
       ) r
    JOIN   questions q ON q.id = r.question_id;
    

    sqlfiddle

    技术综合对比:

    【讨论】:

    • [Err] 错误:在 "(" LINE 5: , count(*) FILTER (WHERE r.response = 'Yes') AS ct_y...处或附近出现语法错误...
    • @JoeneFloresca:我为 pg 9.3 添加了一个解决方案。
    • 哇,非常感谢您的帮助和解释,它工作正常,但最后一个问题,您的 GROUP BY 1?为什么是1?或者我需要那个吗?
    • @JoeneFloresca:在您的小提琴中,您没有“可能”的值,只有 NULL。这与问题相矛盾? GROUP BY 1 是具有位置引用的简写语法,如下所述:stackoverflow.com/a/10398558/939860
    • 是的,你是对的,但如果永远不会是 NULL 值?在不影响结果准确性的情况下使用 GROUP BY 1 还可以吗?
    【解决方案2】:

    你应该试试:

    SELECT a.question_id, 
           SUM(CASE WHEN a.response = 'Yes' THEN 1 ELSE 0 END) AS NumsOfYes, 
           SUM(CASE WHEN a.response = 'No' THEN 1 ELSE 0 END) AS NumsOfNo,
           SUM(CASE WHEN a.response = 'Possibly' THEN 1 ELSE 0 END) AS NumOfPossibly,
           costperlead  * SUM(CASE WHEN a.response = 'Yes' THEN 1 ELSE 0 END) + SUM(CASE WHEN a.response = 'Possibly' THEN 1 ELSE 0 END) AS revenue
    FROM responses a 
         INNER JOIN questions b ON a.question_id = b.id 
    GROUP BY a.question_id, b.costperlead
    

    【讨论】:

    • 我收到一个错误,先生,错误:b.response 列不存在位置:29
    • 感谢您帮助先生,但似乎给了我不正确的结果,因为如果您检查响应表 question_id = 44 有 2 个回答是,那么其他人为空,但根据您的查询结果给出 2是、否和可能?
    • 这会错误地使用聚合函数count(),它会计算除NULL 之外的所有值。表达式产生true 还是falsecount() 无关。
    • 使用 SUM 修改。
    • 您好,非常感谢它运作良好,但@ErwinBrandstetter 对我更有效,加上解释。我会投票代替:) 谢谢!
    猜你喜欢
    • 2015-03-19
    • 1970-01-01
    • 2012-10-24
    • 1970-01-01
    • 2016-11-24
    • 2021-04-01
    • 2020-07-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多