Postgres COUNT 个带有 INNER JOIN 的列值
Posted
技术标签:
【中文标题】Postgres COUNT 个带有 INNER JOIN 的列值【英文标题】:Postgres COUNT number of column values with INNER JOIN 【发布时间】:2015-10-09 11:29:33 【问题描述】:我正在 Postgres 9.3 中创建报告。这是我的SQL Fiddle。
基本上我有两张表,responses
和questions
,结构是:
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;
【问题讨论】:
【参考方案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
技术综合对比:
For absolute performance, is SUM faster or COUNT?【讨论】:
[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
是具有位置引用的简写语法,如下所述:***.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
还是false
与count()
无关。
使用 SUM 修改。
您好,非常感谢它运作良好,但@ErwinBrandstetter 对我更有效,加上解释。我会投票代替:) 谢谢!以上是关于Postgres COUNT 个带有 INNER JOIN 的列值的主要内容,如果未能解决你的问题,请参考以下文章
Postgres INNER JOIN ERROR:模式“bar”不存在