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 条记录,除非您的架构碰巧已经为每个组提供了行号。像上面那样使用会话变量是处理这个问题的一种方法,性能甚至可能也不错。

此处演示:

Rextester