[英]How to sort a list of lists using a sql query?
I have a sql-table that contains records in the following form:我有一个包含以下形式的记录的 sql 表:
(list_id, value)
where the list_id
is an Integer identifiing a specific list and the value
is something that has an order. (list_id, value)
其中list_id
是一个 Integer 标识特定列表,并且value
是具有顺序的东西。
I now struggle to write a sql query that returns all records of that table at first ordered by the rank the list has compared to the other lists and then ordered by the value
.我现在很难编写一个 sql 查询,该查询返回该表的所有记录,首先按列表与其他列表比较的排名排序,然后按
value
排序。
The abstract problem is, that I want to sort a list of lists using sql.抽象的问题是,我想使用 sql 对列表进行排序。
The algorithm to compare two lists is the following:比较两个列表的算法如下:
data CompareRes = FirstSmaller | FirstGreater | Equal deriving Show
compareLists :: Ord a => [a] -> [a] -> CompareRes
compareLists [] [] = Equal
-- Longer lists are considered to be smaller
compareLists _ [] = FirstSmaller
compareLists [] _ = FirstGreater
compareLists (x:xs) (y:ys)
| x < y = FirstSmaller
| x > y = FirstGreater
| otherwise = compareLists xs ys
In my specific case the values are all Date
s.在我的具体情况下,这些值都是
Date
。 So my table looks like this:所以我的表是这样的:
CREATE TABLE `list_date` (
`list_id` INT NOT NULL,
`date` DATE NOT NULL,
PRIMARY KEY (`list_id`, `date`)
);
I'm using a mysql:8.0 database so a solution using WINDOW
-functions is acceptable.我正在使用 mysql:8.0 数据库,因此使用
WINDOW
的解决方案是可以接受的。
INSERT INTO `list_date` VALUES
(1, '2019-11-02'), (1, '2019-11-03'), (1, '2019-11-04'), (1, '2019-11-05'), (1, '2019-11-07'), (1, '2019-11-08'), (1, '2019-11-09'),
(2, '2019-11-01'), (2, '2019-11-03'), (2, '2019-11-04'),
(3, '2019-11-01'), (3, '2019-11-02'), (3, '2019-11-03'),
(4, '2019-11-02'), (4, '2019-11-04'), (4, '2019-11-13'), (4, '2019-11-14'),
(5, '2019-11-03'), (5, '2019-11-04'), (5, '2019-11-05'), (5, '2019-11-10'),
(6, '2019-11-01'), (6, '2019-11-02'), (6, '2019-11-03'), (6, '2019-11-05');
Where I really struggle is to create an expression that calculates the list_rank
:我真正挣扎的地方是创建一个计算
list_rank
的表达式:
SELECT
`list_id`,
`date`,
<PLEASE HELP> as `list_rank`
FROM
`list_date`
ORDER BY
`list_rank`, `date`;
| list_id | date | list_rank |
|---------|------------|-----------|
| 6 | 2019-11-01 | 1 |
| 6 | 2019-11-02 | 1 |
| 6 | 2019-11-03 | 1 |
| 6 | 2019-11-05 | 1 |
| 3 | 2019-11-01 | 2 |
| 3 | 2019-11-02 | 2 |
| 3 | 2019-11-03 | 2 |
| 2 | 2019-11-01 | 3 |
| 2 | 2019-11-03 | 3 |
| 2 | 2019-11-04 | 3 |
| 1 | 2019-11-02 | 4 |
| 1 | 2019-11-03 | 4 |
| 1 | 2019-11-04 | 4 |
| 1 | 2019-11-05 | 4 |
| 1 | 2019-11-07 | 4 |
| 1 | 2019-11-08 | 4 |
| 1 | 2019-11-09 | 4 |
| 4 | 2019-11-02 | 5 |
| 4 | 2019-11-04 | 5 |
| 4 | 2019-11-13 | 5 |
| 4 | 2019-11-14 | 5 |
| 5 | 2019-11-03 | 6 |
| 5 | 2019-11-04 | 6 |
| 5 | 2019-11-05 | 6 |
| 5 | 2019-11-10 | 6 |
or或者
That image is the current live result my application produces.该图像是我的应用程序生成的当前实时结果。 Currently the sorting is implemented using Java.
目前排序是使用 Java 实现的。
After not receiving a better answer, I implemented a solution as suggested by @gordon-linoff:在没有收到更好的答案后,我按照@gordon-linoff 的建议实施了一个解决方案:
SELECT
`list_id`,
`date`
FROM
`list_date`
INNER JOIN (
SELECT `sub`.`list_id`,
GROUP_CONCAT(`sub`.`date` ORDER BY `sub`.`date` SEPARATOR '') as `concat_dates`
FROM `list_date` as `sub`
GROUP BY `sub`.`list_id`
) `all_dates` ON (`all_dates`.`list_id` = `list_date`.`list_id`)
ORDER BY
`all_dates`.`concat_dates`, `date`;
I've also created an SQL Fiddle - So you can play around with your solution.我还创建了一个SQL 小提琴- 所以你可以玩弄你的解决方案。
But this solution does not sort the lists as expected because longer lists are considered bigger than smaller lists.但是此解决方案不会按预期对列表进行排序,因为较长的列表被认为比较小的列表更大。
So I am still hoping to receive a solution that solves 100% of my requirements:)所以我仍然希望能收到一个解决我 100% 需求的解决方案:)
If I understand correctly, you can sort the lists by the dates concatenated together:如果我理解正确,您可以按连接在一起的日期对列表进行排序:
select ld.*
from list_date ld join
(select list_id, group_concat(date) as dates
from ld
group by list_id
) ldc
on ld.list_id = ldc.list_id
order by ldc.dates, ld.date;
Since it's for MySql 8 the window functions can be used for this (yay).由于它适用于 MySql 8,因此 window 函数可用于此(耶)。
Here's a query that first calculates some metrics, to use in the calculation of the ranking:这是一个首先计算一些指标的查询,用于计算排名:
SELECT
list_id,
`date`,
DENSE_RANK() OVER (ORDER BY ListMinDate ASC, ListCount DESC, ListMaxDate, list_id) AS list_rank
FROM
(
SELECT
list_id,
`date`,
COUNT(*) OVER (PARTITION BY list_id) AS ListCount,
MIN(`date`) OVER (PARTITION BY list_id) AS ListMinDate,
MAX(`date`) OVER (PARTITION BY list_id) AS ListMaxDate
FROM list_date
) q
ORDER BY list_rank, `date`
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.