mysql - 选择有限行的重复列
mysql - selecting limited rows of duplicate columns
我有什么
所以我运行这个声明:
SELECT
i.id,
i.item_id,
v.item_to_map_id,
i.date,
COALESCE( SUM(CAST(CAST(v.score AS char) AS SIGNED)), 0 ) AS score
FROM item_to_map i
LEFT JOIN
vote_item v
ON i.id = v.item_to_map_id
GROUP BY
i.id, i.item_id, i.date, v.item_to_map_id
ORDER BY
item_id asc, score desc;
我得到以下 table:
+----+---------+----------------+---------------------+-------+
| id | item_id | item_to_map_id | date | score |
+----+---------+----------------+---------------------+-------+
| 1 | 1 | 1 | 2017-07-05 09:38:23 | 3 |
| 3 | 1 | 3 | 2017-07-05 09:38:23 | 0 |
| 2 | 1 | 2 | 2017-07-05 09:38:23 | -1 |
| 4 | 2 | NULL | 2017-07-05 09:38:23 | 0 |
| 5 | 2 | NULL | 2017-07-05 09:38:23 | 0 |
| 6 | 2 | NULL | 2017-07-05 09:38:24 | 0 |
+----+---------+----------------+---------------------+-------+
我想要做的是 select 重复 item_id
中的第一个 X 基于某些顺序,例如分数或日期。
我试过的
我查看了这个答案 并尝试了一个修改版本:
SELECT
i.id,
i.item_id,
v.item_to_map_id,
i.date,
COALESCE( SUM(CAST(CAST(v.score AS char) AS SIGNED)), 0 ) AS score
FROM item_to_map i
LEFT JOIN
vote_item v
ON i.id = v.item_to_map_id
WHERE
(
SELECT
COUNT(*)
FROM
item_to_map i2
WHERE
i2.item_id = i.item_id
) < 3
GROUP BY
i.id, i.item_id, i.date, v.item_to_map_id
ORDER BY item_id asc, score desc;
然而这个returns我没有结果
如我所料
如果按分数排序:
+----+---------+----------------+---------------------+-------+
| id | item_id | item_to_map_id | date | score |
+----+---------+----------------+---------------------+-------+
| 1 | 1 | 1 | 2017-07-05 09:38:23 | 3 |
| 3 | 1 | 3 | 2017-07-05 09:38:23 | 0 |
| 4 | 2 | NULL | 2017-07-05 09:38:23 | 0 |
| 5 | 2 | NULL | 2017-07-05 09:38:23 | 0 |
+----+---------+----------------+---------------------+-------+
您可以使用模拟行号功能的会话变量来实现此目的:
SET @row_number = 0;
SET @item_id = 1;
SELECT t.id, t.item_id, t.item_to_map_id, t.date, t.score
FROM
(
SELECT
@row_number:=CASE WHEN @item_id = t.item_id
THEN @row_number + 1 ELSE 1 END AS rn,
@item_id:=t.item_id AS item_id,
t.id, t.item_to_map_id, t.date, t.score
FROM
(
SELECT
i.id,
i.item_id,
v.item_to_map_id,
i.date,
COALESCE( SUM(CAST(CAST(v.score AS char) AS SIGNED)), 0 ) AS score
FROM item_to_map i
LEFT JOIN vote_item v
ON i.id = v.item_to_map_id
GROUP BY
i.id, i.item_id, i.date, v.item_to_map_id
) t
ORDER BY
t.item_id, t.score DESC
) t
WHERE t.rn <= 2 -- this restricts to the first two rows per item_id group
-- as ordered by the logic in your ORDER BY clause
据我所知,没有很好的方法来获取 MySQL 中组的前 X 条记录,除非您的架构碰巧已经为每个组提供了行号。像上面那样使用会话变量是处理这个问题的一种方法,性能甚至可能也不错。
此处演示:
我有什么
所以我运行这个声明:
SELECT
i.id,
i.item_id,
v.item_to_map_id,
i.date,
COALESCE( SUM(CAST(CAST(v.score AS char) AS SIGNED)), 0 ) AS score
FROM item_to_map i
LEFT JOIN
vote_item v
ON i.id = v.item_to_map_id
GROUP BY
i.id, i.item_id, i.date, v.item_to_map_id
ORDER BY
item_id asc, score desc;
我得到以下 table:
+----+---------+----------------+---------------------+-------+
| id | item_id | item_to_map_id | date | score |
+----+---------+----------------+---------------------+-------+
| 1 | 1 | 1 | 2017-07-05 09:38:23 | 3 |
| 3 | 1 | 3 | 2017-07-05 09:38:23 | 0 |
| 2 | 1 | 2 | 2017-07-05 09:38:23 | -1 |
| 4 | 2 | NULL | 2017-07-05 09:38:23 | 0 |
| 5 | 2 | NULL | 2017-07-05 09:38:23 | 0 |
| 6 | 2 | NULL | 2017-07-05 09:38:24 | 0 |
+----+---------+----------------+---------------------+-------+
我想要做的是 select 重复 item_id
中的第一个 X 基于某些顺序,例如分数或日期。
我试过的
我查看了这个答案 并尝试了一个修改版本:
SELECT
i.id,
i.item_id,
v.item_to_map_id,
i.date,
COALESCE( SUM(CAST(CAST(v.score AS char) AS SIGNED)), 0 ) AS score
FROM item_to_map i
LEFT JOIN
vote_item v
ON i.id = v.item_to_map_id
WHERE
(
SELECT
COUNT(*)
FROM
item_to_map i2
WHERE
i2.item_id = i.item_id
) < 3
GROUP BY
i.id, i.item_id, i.date, v.item_to_map_id
ORDER BY item_id asc, score desc;
然而这个returns我没有结果
如我所料
如果按分数排序:
+----+---------+----------------+---------------------+-------+
| id | item_id | item_to_map_id | date | score |
+----+---------+----------------+---------------------+-------+
| 1 | 1 | 1 | 2017-07-05 09:38:23 | 3 |
| 3 | 1 | 3 | 2017-07-05 09:38:23 | 0 |
| 4 | 2 | NULL | 2017-07-05 09:38:23 | 0 |
| 5 | 2 | NULL | 2017-07-05 09:38:23 | 0 |
+----+---------+----------------+---------------------+-------+
您可以使用模拟行号功能的会话变量来实现此目的:
SET @row_number = 0;
SET @item_id = 1;
SELECT t.id, t.item_id, t.item_to_map_id, t.date, t.score
FROM
(
SELECT
@row_number:=CASE WHEN @item_id = t.item_id
THEN @row_number + 1 ELSE 1 END AS rn,
@item_id:=t.item_id AS item_id,
t.id, t.item_to_map_id, t.date, t.score
FROM
(
SELECT
i.id,
i.item_id,
v.item_to_map_id,
i.date,
COALESCE( SUM(CAST(CAST(v.score AS char) AS SIGNED)), 0 ) AS score
FROM item_to_map i
LEFT JOIN vote_item v
ON i.id = v.item_to_map_id
GROUP BY
i.id, i.item_id, i.date, v.item_to_map_id
) t
ORDER BY
t.item_id, t.score DESC
) t
WHERE t.rn <= 2 -- this restricts to the first two rows per item_id group
-- as ordered by the logic in your ORDER BY clause
据我所知,没有很好的方法来获取 MySQL 中组的前 X 条记录,除非您的架构碰巧已经为每个组提供了行号。像上面那样使用会话变量是处理这个问题的一种方法,性能甚至可能也不错。
此处演示: