【问题标题】:is there a query to fetch first two items associated with an id MYSQL是否有查询来获取与 id MYSQL 关联的前两个项目
【发布时间】:2022-01-18 05:21:27
【问题描述】:

我在 mysql select player_id, obj_category from table order by player_id; 中使用以下查询提取了一个临时表

输出如图,每个id关联多个对象类别

电流输出

player_id obj_category created_time
19855. Electronics 2021-09-21 18:02:17
19855. House. 2021-09-21 18:03:20
19855. Car. 2021-09-21 18:03:54
19855. Toys. 2021-09-21 18:04:17
19855 Sweets. 2021-09-21 18:05:13
19907 Business 2021-09-21 15:02:17
19907 Books. 2021-09-21 15:02:40
19907 House. 2021-09-21 15:04:14
19907 Books 2021-09-21 15:05:34
19908 Toys 2021-09-21 14:04:17
19908 Mobile 2021-09-21 14:07:19
19908 Sports 2021-09-21 14:08:43
19908 Electronics. 2021-09-21 14:02:17

在这个示例中,我有 3 个 id,(19855,19907,19908)。我想创建一个查询,我将只检索与每个 id 关联的前 2 个 obj_category。它们将根据每个 id 每个对象的创建时间进行排序

预期输出:

player_id obj_category
19855. Electronics
19855. House.
19907 Business
19907 Books
19908 Toys
19908 Mobile

我尝试了多个代码,例如

,但是我无法达到该输出,也找不到任何指导来帮助我。

提前谢谢你

【问题讨论】:

  • 定义“第一”。先插入?首先是按顺序订购时,首先是基于某个日期?
  • 一个表在设计上是未排序的,所以没有另一个 cloumn 来确定哪个是没有第一个的顺序
  • 尝试自己编写一些东西,如果不起作用,请具体向我们展示您所做的事情,以便我们为您提供帮助。您启动它,然后我们提供帮助。我们不是为你写的。向我们展示您尝试过的实际代码,然后描述发生的事情和不正确的事情,然后我们可以从那里帮助您。如果您先自己尝试一下,您可能会非常接近答案。
  • @AndyLester 谢谢安迪。这是我第一次在 Stackoverflow 上发帖,我对 sql 也有点陌生,我还在学习。下次我会这样做
  • @IvoP 对。我在临时表查询中添加了一个列,用于标识类别的顺序。感谢您指出这一点

标签: mysql sql


【解决方案1】:

MYSQL 8 为此提供了窗口函数 ROW_NUMBER。

如果你使用旧版本,你必须use

CREATE TABLE players (
  `player_id` INTEGER,
  `obj_category` VARCHAR(12),
  `created_time` DATETIME
);

INSERT INTO players
  (`player_id`, `obj_category`, `created_time`)
VALUES
  ('19855.', 'Electronics', '2021-09-21 18:02:17'),
  ('19855.', 'House.', '2021-09-21 18:03:20'),
  ('19855.', 'Car.', '2021-09-21 18:03:54'),
  ('19855.', 'Toys.', '2021-09-21 18:04:17'),
  ('19855', 'Sweets.', '2021-09-21 18:05:13'),
  ('19907', 'Business', '2021-09-21 15:02:17'),
  ('19907', 'Books.', '2021-09-21 15:02:40'),
  ('19907', 'House.', '2021-09-21 15:04:14'),
  ('19907', 'Books', '2021-09-21 15:05:34'),
  ('19908', 'Toys', '2021-09-21 14:04:17'),
  ('19908', 'Mobile', '2021-09-21 14:07:19'),
  ('19908', 'Sports', '2021-09-21 14:08:43'),
  ('19908', 'Electronics.', '2021-09-21 14:02:17');
SELECT 
`player_id`, `obj_category`
FROM
(SELECT
`player_id`, `obj_category`, `created_time`,
ROW_NUMBER() OVER(PARTITION BY `player_id` ORDER BY `created_time` ASC) rn FROM players) t1
WHERE rn <= 2
player_id | obj_category --------: | :----------- 19855 |电子产品 19855 |屋。 19907 |商业 19907 |图书。 19908 |电子产品。 19908 |玩具

db小提琴here

【讨论】:

    【解决方案2】:

    您需要决定是什么决定了与 ID 相关的 n 项中的哪一项被选为“前两项”。当您这样做时,您可以尝试将 ROW_NUMBER() 函数与公用表表达式 (CTE) 结合使用:

    WITH data AS
    (
    select player_id, obj_category, ROW_NUMBER() OVER (PARTITION BY player_id ORDER BY obj_category) as row_priority from table 
    )
    SELECT * FROM data WHERE row_priority <= 2;
    

    ROW_NUMBER() OVER (PARTITION BY &lt;foo&gt; ORDER BY &lt;bar&gt;) 将为每个生成唯一的索引顺序(在您的情况下是玩家 ID;每个 ID 将获得 row_priority 1、2、3、4 等),其中该索引的顺序将由谓词确定,在我的示例中,这只是类别名称的字母顺序。因此,例如对于玩家 id 19855,您将获得汽车 (1)、糖果 (2)、玩具 (3)。最后,您只需过滤 1 或 2(小于或等于 2)。

    【讨论】:

    • 你说的很清楚。非常感谢@MarcinJ
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    相关资源
    最近更新 更多