然后使用前 10 个查询来搜索与其关联的所有记录

Using a top 10 query to then search all records associated with them

总的来说,我对 sql 不是很有经验,我正在尝试完成一项非常具体的任务 - 我想首先 运行 查询以获取我所有的 ID点击次数最多的单元,然后再次从那个 运行 获取特定时间 period.For 中这些 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

结果是 return:

"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

我不确定这是否是我应该走的路线,或者我是否应该尝试自我加入 - 无论哪种方式都不确定如何纠正现在发生的事情。

当您将第一个查询插入第二个查询并在 in 子句中使用它时,您仍然 return 两列,而 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

或者使用第一个查询作为派生 table 并加入它。

使用 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'
    
  • 因为子查询只有returns一个单独的列(entity),它与USING子句合并,列名是明确的,我们不这里不需要 table 资格。

  • LIMIT 10 按计数排序后很可能会产生歧义。多行可以并列为第 10 行。没有 ORDER BY 中的附加项目,Postgres returns 任意选择,这可能是也可能不是。但是查询的结果可以在调用之间发生变化,而不会对基础数据进行任何更改。通常,这是不可取的,您应该将列或表达式添加到列表中以 break ties.

  • count(*)count(status_code) 快一点并且做同样的事情 - 除非 status_code 可以为空,在这种情况下你会得到 0 作为此行的计数(count() 从不 returns null)而不是实际的行计数,这要么是无用的,要么是错误的。在这里使用任何一种方式 count(*)

  • GROUP BY 1, 2只是语法上的shorthand。详情:

    • Select first row in each GROUP BY group?