0

我有的

我在 MySQL 数据库(版本 5.6.35)中有以下两个表。

CREATE TABLE `Runs` (
  `Name` varchar(200) NOT NULL,
  `Run` varchar(200) NOT NULL,
  `Points` int(11) NOT NULL
) DEFAULT CHARSET=latin1;

INSERT INTO `Runs` (`Name`, `Run`, `Points`) VALUES
('John', 'A08', 12),
('John', 'A09', 3),
('John', 'A01', 15),
('Kate', 'A02', 92),
('Kate', 'A03', 1),
('Kate', 'A04', 33),
('Peter', 'A05', 8),
('Peter', 'A06', 14),
('Peter', 'A07', 5);

CREATE TABLE `Users` (
  `Name` varchar(500) NOT NULL,
  `NumberOfRun` int(11) NOT NULL
) DEFAULT CHARSET=latin1;

INSERT INTO `Users` (`Name`, `NumberOfRun`) VALUES
('John', 2),
('Kate', 1),
('Peter', 3);

ALTER TABLE `Runs`
  ADD PRIMARY KEY (`Run`);

我的目标是什么

  • 约翰有Users.NumberOfRun=2,所以我将从Runs表中提取 2 个顶级记录
  • 凯特有,所以我会从表中Users.NumberOfRun=1提取第一条记录Runs
  • 彼得有Users.NumberOfRun=3,所以我将从Runs表中提取 3 条最高记录

我想得出以下结果

+-------+-----+--------+
| Name  | Run | Points |
+-------+-----+--------+
| John  | A01 |     15 |
| John  | A08 |     12 |
| Kate  | A02 |     92 |
| Peter | A06 |     14 |
| Peter | A05 |      8 |
| Peter | A07 |      5 |
+-------+-----+--------+

我试过的

首先,如果是 SQL Server,我会对 Runs 表使用函数ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ) AS [rn],然后JOIN在.UsersUsers.NumberOfRun<=[rn]

我已阅读文档,但似乎PARTITONING在 MySQL 中它从 8.X 版本开始可用,但我使用的是 5.6.X 版本。

最后,我根据这个 Stackoverflow 答案尝试了这个查询:

SELECT t0.Name,t0.Run
FROM Runs AS t0
LEFT JOIN Runs AS t1 ON t0.Name=t1.Name AND t0.Run=t1.Run AND t1.Points>t0.Points
WHERE t1.Points IS NULL;

但它没有给我行号,这基本上是为了让我按照上述方式进行 JOIN。

SQL Fiddle 这个例子

4

1 回答 1

2

'group_concat' 和 'find_in_set' 的组合,然后使用 'find_in_set' 返回的位置进行过滤将为您完成这项工作。

GROUP_CONCAT 将首先按点的降序对数据进行排序。

GROUP_CONCAT(Run ORDER BY Points DESC)

FIND_IN_SET 然后将检索您想要包含在结果中的行数。

FIND_IN_SET(Run, grouped_run) BETWEEN 1 AND Users.NumberOfRun

以下查询应该适合您。

SELECT
  Runs.*
FROM
  Runs 
  INNER JOIN (
    SELECT
      Name, GROUP_CONCAT(Run ORDER BY Points DESC) grouped_run
    FROM
      Runs
    GROUP BY Name
  ) group_max ON Runs.Name = group_max.Name
  INNER JOIN Users ON Users.Name = Runs.Name
  WHERE FIND_IN_SET(Run, grouped_run) BETWEEN 1 AND Users.NumberOfRun
ORDER BY
  Runs.Name Asc, Runs.Points DESC;
于 2018-07-17T09:04:36.070 回答