mysql - 对几个查询的结果求和,然后在 SQL 中找到前 5 个

标签 mysql select group-by greatest-n-per-group

我有 3 个问题:

table: pageview
SELECT event_id, count(*) AS pageviews 
FROM pageview 
GROUP BY event_id
ORDER BY pageviews DESC, rand()
LIMIT 1000

table: upvote
SELECT event_id, count(*) AS upvotes 
FROM upvote
GROUP BY event_id
ORDER BY upvotes DESC, rand()
LIMIT 1000

table: attending
SELECT event_id, count(*) AS attendants
FROM attending
GROUP BY event_id
ORDER BY attendants DESC, rand()
LIMIT 1000

我想将所有 3 个查询的 event_id 按金额排序,然后选择前 5 个。我该怎么做?

编辑:这是我为实现它所做的:

SELECT event_id, sum(amount) AS total
FROM (
(SELECT event_id, count(*) AS amount
FROM   pageview 
GROUP  BY event_id
ORDER  BY amount DESC, rand()
LIMIT  1000)

UNION ALL
(SELECT event_id, count(*) as amount
FROM   upvote
GROUP  BY event_id
ORDER  BY amount DESC, rand()
LIMIT  1000)

UNION ALL
(SELECT event_id, count(*) as amount
FROM   attending
GROUP  BY event_id
ORDER  BY amount DESC, rand()
LIMIT  1000)
) x
GROUP  BY 1
ORDER  BY  sum(amount) DESC
LIMIT  5;

最佳答案

UNION 所有三个查询的结果行,然后选择具有最高数量 的 5 行:

(SELECT event_id, count(*) AS amount
FROM   pageview 
GROUP  BY event_id
ORDER  BY pageviews DESC, rand()
LIMIT  1000)

UNION ALL
(SELECT event_id, count(*)
FROM   upvote
GROUP  BY event_id
ORDER  BY upvotes DESC, rand()
LIMIT  1000)

UNION ALL
(SELECT event_id, count(*)
FROM   attending
GROUP  BY event_id
ORDER  BY attendants DESC, rand()
LIMIT  1000)

ORDER  BY 2 DESC
LIMIT  5;

The manual:

To apply ORDER BY or LIMIT to an individual SELECT, place the clause inside the parentheses that enclose the SELECT.

UNION ALL 以保留重复项。


为每个 event_id 添加计数:

SELECT event_id, sum(amount) AS total
FROM (
   (SELECT event_id, count(*) AS amount
    FROM   pageview 
    GROUP  BY event_id
    ORDER  BY pageviews DESC, rand()
    LIMIT  1000)
    
    UNION ALL
    (SELECT event_id, count(*)
    FROM   upvote
    GROUP  BY event_id
    ORDER  BY upvotes DESC, rand()
    LIMIT  1000)
    
    UNION ALL
    (SELECT event_id, count(*)
    FROM   attending
    GROUP  BY event_id
    ORDER  BY attendants DESC, rand()
    LIMIT  1000)
    ) x
GROUP  BY 1
ORDER  BY sum(amount) DESC
LIMIT  5;

这里棘手的部分是并非每个 event_id 都会出现在所有三个基本查询中。因此请注意 JOIN 不会完全丢失行,并且添加不会变成 NULL

使用UNION ALL,而不是UNION。您不想删除相同的行,而是想将它们相加。

xAS x 的表别名和简写。子查询需要有一个名称。这里可以是任何其他名称。

SOL 特性 FULL OUTER JOIN 没有在 MySQL 中实现(我上次检查过),所以你必须凑合使用 UNIONFULL OUTER JOIN 将在不丢失行的情况下连接所有三个基本查询。

后续问题的答案

SELECT event_id, sum(amount) AS total
FROM (
   (SELECT event_id, count(*) / 100 AS amount
    FROM   pageview ... )
    
    UNION ALL
    (SELECT event_id, count(*) * 5 
    FROM   upvote ... )
    
    UNION ALL
    (SELECT event_id, count(*) * 10
    FROM   attending ... )
    ) x
GROUP  BY 1
ORDER  BY  sum(amount) DESC
LIMIT  5;

或者,以多种方式使用碱基计数:

SELECT event_id
      ,sum(CASE source
              WHEN 'p' THEN amount / 100
              WHEN 'u' THEN amount * 5
              WHEN 'a' THEN amount * 10
              ELSE 0
           END)  AS total
FROM (
   (SELECT event_id, 'p'::text AS source, count(*) AS amount
    FROM   pageview ... )
    
    UNION ALL
    (SELECT event_id, 'u'::text, count(*)
    FROM   upvote ... )
    
    UNION ALL
    (SELECT event_id, 'a'::text, count(*)
    FROM   attending ... )
    ) x
GROUP  BY 1
ORDER  BY 2 DESC
LIMIT  5;

关于mysql - 对几个查询的结果求和,然后在 SQL 中找到前 5 个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8528787/

相关文章:

mysql - 在第一次选择的基础上进行第二次选择

MySQL 查询 2 个表在旁边加入列

python - 比较单列的行元素。如果有 2 个连续的 L,则从 High 列中选择最低的,忽略其他。相反,如果 2 L

mysql - 按查询分组仅返回最新结果 - Codeigniter

r - 如何在 R 中对数据表进行子集化、分组和计算 j

php - 日期等于或大于 DateTime 的 Laravel Eloquent

mysql - 使用 MySQL CASE 表达式进行聚合

java - 用户输入内容后,JSP页面不会移动到另一个页面

php - SQL - 如何获取创建的同一日期的最新数据

mysql - sql删除 double 值