按列对行进行排序,同时将具有公共列的行放在一起
Order rows by column whilst keeping rows with a common column together
我是 运行 MariaDB 5.5,相当于 MySQL 5.5.
我有以下测试数据
CREATE TABLE `dev_test` (
`id` INT NOT NULL AUTO_INCREMENT ,
`date` DATE NOT NULL ,
`venue` INT NOT NULL ,
PRIMARY KEY (`id`)
) ENGINE = InnoDB;
INSERT INTO `dev_test` (`id`, `date`, `venue`) VALUES (NULL, '2019-08-01', '2'),
(NULL, '2019-09-01', '1'), (NULL, '2019-10-01', '2');
INSERT INTO `dev_test` (`id`, `date`, `venue`) VALUES (NULL, '2019-11-01', '3');
我希望对场地和活动进行排序,以便下一个活动的场地排在第一位,然后是该场地的所有其他活动。然后列出下一个尚未准备好的事件。
所以我想要这些数据:
Event ID 1 - 2019-08-01 Venue 2
Event ID 3 - 2019-10-01 Venue 2
Event ID 2 - 2019-09-01 Venue 1
Event ID 4 - 2019-11-01 Venue 3
我可以按任意顺序获取所有事件,然后使用 PHP 对它们进行排序。
或者我可以 select 和
SELECT venue FROM `dev_test` GROUP BY venue ORDER BY date;
然后使用 PHP 一次获取一个按日期排序的场地
SELECT * FROM `dev_test` WHERE venue = 2 ORDER BY date;
SELECT * FROM `dev_test` WHERE venue = 1 ORDER BY date;
但是在纯 MySQL (MariaDB) 中有没有好的方法来做到这一点?
也许可以通过某种方式为所有场地提供与该场地最早日期相同的临时日期列?
或者我应该在 PHP 中完成吗?
抱歉标题太血腥了。我试图使“按日期排序事件,同时将事件保持在同一位置”更通用。
您可以尝试以下 - 使用 order by venue desc, date asc
SELECT * FROM `dev_test`
order by venue desc, date asc
试试这个查询,我认为这对你有帮助
SELECT t2.* FROM
(SELECT venue FROM dev_test GROUP BY venue ORDER BY date) AS t1
LEFT JOIN (SELECT * FROM dev_test ORDER BY date) AS t2 ON t1.venue=t2.venue
这里是结果
您可以使用带有 CTE 的 window 函数来实现此目的(注意:需要 MySQL 8+:
WITH added_initial_date
AS (SELECT id,
date,
venue,
FIRST_VALUE(date)
OVER(
PARTITION BY venue
ORDER BY date) AS 'initial_date'
FROM dev_test),
ranked
AS (SELECT id,
date,
venue,
initial_date,
RANK()
OVER(
ORDER BY initial_date ASC) AS position
FROM added_initial_date)
SELECT id,
date,
venue
FROM ranked
ORDER BY position ASC, date ASC;
也许它不是最有效的,但它确实有效。
更新:添加了按日期排序以首先获得最接近的记录。这是 db-fiddle: https://www.db-fiddle.com/f/puYqhDF53ocRiRys61XH53/0
例如:
SELECT a.*
FROM dev_test a
LEFT
JOIN (SELECT * FROM dev_test ORDER BY date DESC LIMIT 1) b
ON b.venue = a.venue
ORDER
BY b.id IS NULL, date DESC;
根据样本数据,这假设日期是唯一的
我是 运行 MariaDB 5.5,相当于 MySQL 5.5.
我有以下测试数据
CREATE TABLE `dev_test` (
`id` INT NOT NULL AUTO_INCREMENT ,
`date` DATE NOT NULL ,
`venue` INT NOT NULL ,
PRIMARY KEY (`id`)
) ENGINE = InnoDB;
INSERT INTO `dev_test` (`id`, `date`, `venue`) VALUES (NULL, '2019-08-01', '2'),
(NULL, '2019-09-01', '1'), (NULL, '2019-10-01', '2');
INSERT INTO `dev_test` (`id`, `date`, `venue`) VALUES (NULL, '2019-11-01', '3');
我希望对场地和活动进行排序,以便下一个活动的场地排在第一位,然后是该场地的所有其他活动。然后列出下一个尚未准备好的事件。
所以我想要这些数据:
Event ID 1 - 2019-08-01 Venue 2
Event ID 3 - 2019-10-01 Venue 2
Event ID 2 - 2019-09-01 Venue 1
Event ID 4 - 2019-11-01 Venue 3
我可以按任意顺序获取所有事件,然后使用 PHP 对它们进行排序。
或者我可以 select 和
SELECT venue FROM `dev_test` GROUP BY venue ORDER BY date;
然后使用 PHP 一次获取一个按日期排序的场地
SELECT * FROM `dev_test` WHERE venue = 2 ORDER BY date;
SELECT * FROM `dev_test` WHERE venue = 1 ORDER BY date;
但是在纯 MySQL (MariaDB) 中有没有好的方法来做到这一点?
也许可以通过某种方式为所有场地提供与该场地最早日期相同的临时日期列?
或者我应该在 PHP 中完成吗?
抱歉标题太血腥了。我试图使“按日期排序事件,同时将事件保持在同一位置”更通用。
您可以尝试以下 - 使用 order by venue desc, date asc
SELECT * FROM `dev_test`
order by venue desc, date asc
试试这个查询,我认为这对你有帮助
SELECT t2.* FROM
(SELECT venue FROM dev_test GROUP BY venue ORDER BY date) AS t1
LEFT JOIN (SELECT * FROM dev_test ORDER BY date) AS t2 ON t1.venue=t2.venue
这里是结果
您可以使用带有 CTE 的 window 函数来实现此目的(注意:需要 MySQL 8+:
WITH added_initial_date
AS (SELECT id,
date,
venue,
FIRST_VALUE(date)
OVER(
PARTITION BY venue
ORDER BY date) AS 'initial_date'
FROM dev_test),
ranked
AS (SELECT id,
date,
venue,
initial_date,
RANK()
OVER(
ORDER BY initial_date ASC) AS position
FROM added_initial_date)
SELECT id,
date,
venue
FROM ranked
ORDER BY position ASC, date ASC;
也许它不是最有效的,但它确实有效。
更新:添加了按日期排序以首先获得最接近的记录。这是 db-fiddle: https://www.db-fiddle.com/f/puYqhDF53ocRiRys61XH53/0
例如:
SELECT a.*
FROM dev_test a
LEFT
JOIN (SELECT * FROM dev_test ORDER BY date DESC LIMIT 1) b
ON b.venue = a.venue
ORDER
BY b.id IS NULL, date DESC;
根据样本数据,这假设日期是唯一的