我对sql一般都没有超级经验,而且我正在尝试完成一项非常具体的任务 - 我想首先运行一个查询来获取所有单位的ID,并获得最高的点击数,然后从该运行再次获取在特定时间段内这些ID的所有类型的命中的消息和计数。对于第一个查询,我有这个:
SELECT entity, count(entity) as Count
from plugin_status_alerts
where entered BETWEEN now() - INTERVAL '14 days' AND now()
group by entity
order by count(entity) DESC
limit 10
导致此回报:
"38792";3
"39416";2
"37796";2
"39145";2
"37713";2
"37360";2
"37724";2
"39152";2
"39937";2
"39667";2
然后使用该结果集然后运行另一个按实体和status_code排序的查询。我试过这样的事情:
SELECT status_code, entity, COUNT(status_code) statusCount
FROM plugin_status_alerts
where updated BETWEEN now() - INTERVAL '14 days' AND now() AND entity IN
(SELECT id.entity, count(id.entity) as Count
from plugin_status_alerts id
where id.updated BETWEEN now() - INTERVAL '14 days' AND now()
group by id.entity
order by count(id.entity) DESC
limit 10
)
GROUP BY status_code, entity
但我收到了错误
ERROR: subquery has too many columns
我不确定这是否是我应该去的路线,或者我是否应该尝试自我加入 - 不管怎样纠正现在发生的事情。
答案 0 :(得分:1)
使用JOIN
代替IN (subquery)
。这通常更快,如果需要,您可以使用子查询中的其他值(例如每entity
的总计数):
SELECT entity, status_code, count(*) AS status_ct
FROM (
SELECT entity -- not adding count since you don't use it, but you could
FROM plugin_status_alerts
WHERE entered BETWEEN now() - interval '14 days' AND now()
GROUP BY entitiy
ORDER BY count(*) DESC, entitiy -- as tie breaker to get stable result
LIMIT 10
) sub
JOIN plugin_status_alerts USING (entity)
WHERE updated BETWEEN now() - interval '14 days' AND now()
GROUP BY 1, 2;
如果您没有按设计进行日后记录,则可以简化:
WHERE entered > now() - interval '14 days'
由于子查询只返回与entity
子句合并的单个列(USING
),因此列名称是明确的,我们不需要表格限定。
LIMIT 10
可能不明确。多行可以绑定第10行。如果没有ORDER BY
中的其他项目,Postgres将返回任意选择,这可能会也可能不会。但是查询的结果可以在调用之间进行更改,而不会对基础数据进行任何更改。通常情况下,这是不可取的,您应该在列表中添加列或表达式以打破关系。
count(*)
比count(status_code)
快一点并且做同样的事情 - 除非status_code
可以为null,在这种情况下,您将获得0
作为计数此行(count()
永远不会返回null)而不是实际的行计数,这是无用的或主动错误的。在此处使用count(*)
。
GROUP BY 1, 2
只是语法简写。详细说明:
答案 1 :(得分:0)
当您将第一个查询插入第二个查询并在in
子句中使用时,当in
只需要一个时,您仍会返回两列。要么这样做:
SELECT status_code, entity, COUNT(status_code) statusCount
FROM plugin_status_alerts
where updated BETWEEN now() - INTERVAL '14 days' AND now()
AND entity IN (
SELECT id.entity
from plugin_status_alerts id
where id.updated BETWEEN now() - INTERVAL '14 days' AND now()
group by id.entity
order by count(id.entity) DESC
limit 10
)
GROUP BY status_code, entity
或者将第一个查询用作派生表并与之连接。