[英]Calculating difference between min value and each row's value
我有一個數據庫表,其中包含一個人的ID,名稱和時間(以毫秒為單位,存儲為int
)。 例如:
| id | name | totalTime |
| --- | ------ | --------- |
| 1 | Bob | 16280 |
| 2 | Andy | 17210 |
| 3 | Bill | 15320 |
| 4 | Matt | 14440 |
| 5 | Steven | 17570 |
| 6 | Tom | NULL |
| 7 | Angus | 17210 |
| 8 | Will | NULL |
| 9 | Jack | 17410 |
| 10 | Alex | 16830 |
不一定所有人都有時間(因此為空)。
我想再有兩列-一列顯示每個人的排名/位置,另一列顯示最佳(即最小)時間與每一行時間之間的時間差(毫秒)。
我設法寫了一個MySQL 8.x查詢,它執行的排名:
SELECT id, name, totalTime,
(CASE WHEN totalTime IS NOT NULL THEN RANK() OVER ( PARTITION BY (CASE WHEN totalTime IS NOT NULL THEN 1 ELSE 0 END) ORDER BY totalTime ) END) totalRank
FROM results
ORDER BY -totalRank DESC;
...並輸出以下內容:
| id | name | totalTime | totalRank |
| --- | ------ | --------- | --------- |
| 4 | Matt | 14440 | 1 |
| 3 | Bill | 15320 | 2 |
| 1 | Bob | 16280 | 3 |
| 10 | Alex | 16830 | 4 |
| 2 | Andy | 17210 | 5 |
| 7 | Angus | 17210 | 5 |
| 9 | Jack | 17410 | 7 |
| 5 | Steven | 17570 | 8 |
| 6 | Tom | NULL | NULL |
| 8 | Will | NULL | NULL |
...但是無法找出SQL添加帶有時差的另一列。
以下是我想要但無法弄清楚該怎么做的示例:
| id | name | totalTime | totalRank | difference |
| --- | ------ | --------- | --------- | ---------- |
| 4 | Matt | 14440 | 1 | 0 |
| 3 | Bill | 15320 | 2 | 880 |
| 1 | Bob | 16280 | 3 | 1840 |
| 10 | Alex | 16830 | 4 | 2390 |
| 2 | Andy | 17210 | 5 | 2770 |
| 7 | Angus | 17210 | 5 | 2770 |
| 9 | Jack | 17410 | 7 | 2970 |
| 5 | Steven | 17570 | 8 | 3130 |
| 6 | Tom | NULL | NULL | NULL |
| 8 | Will | NULL | NULL | NULL |
我可以將其作為數據庫提琴手使用: https : //www.db-fiddle.com/f/gQvSeij2EKSufYp9VjbDav/0
在此先感謝您的幫助!
您可以使用CTE
來獲取最小totalTime
並使用它來計算difference
:
WITH cte as (SELECT MIN(totalTime) minTotalTime FROM results)
SELECT id, name, totalTime,
CASE WHEN totalTime IS NOT NULL
THEN RANK() OVER (PARTITION BY (
CASE
WHEN totalTime IS NOT NULL THEN 1
ELSE 0
END
) ORDER BY totalTime)
END totalRank,
totalTime - (SELECT minTotalTime from cte) difference
FROM results
ORDER BY -totalRank DESC;
參見演示 。
結果:
| id | name | totalTime | totalRank | difference |
| --- | ------ | --------- | --------- | ---------- |
| 4 | Matt | 14440 | 1 | 0 |
| 3 | Bill | 15320 | 2 | 880 |
| 1 | Bob | 16280 | 3 | 1840 |
| 10 | Alex | 16830 | 4 | 2390 |
| 2 | Andy | 17210 | 5 | 2770 |
| 7 | Angus | 17210 | 5 | 2770 |
| 9 | Jack | 17410 | 7 | 2970 |
| 5 | Steven | 17570 | 8 | 3130 |
| 6 | Tom | | | |
| 8 | Will | | | |
SELECT subtable.id,
subtable.NAME,
subtable.totalTime,
subtable.diff,
IIF(subtable.totalTime IS NULL,NULL,subtable.rowno) as bisi
FROM (
select *,
ROW_NUMBER() OVER (ORDER BY totalTime desc) as rowno,
totalTime -
(
select min(rst.totalTime)
from results rst) as diff
from results) subtable;
我會在MS-SQL或MYSQL中這樣做
SELECT subtable.id,
subtable.NAME,
subtable.totalTime,
subtable.diff,
IF (subtable.totalTime IS NULL, NULL, subtable.rowno) as bisi
FROM (
select *,
ROW_NUMBER() OVER (ORDER BY totalTime desc) as rowno,
totalTime -
(
select min(rst.totalTime)
from results rst) as diff
from results) subtable;
添加min()窗口函數
SELECT id, name, totalTime,
(CASE WHEN totalTime IS NOT NULL THEN RANK() OVER ( PARTITION BY (CASE WHEN totalTime IS NOT NULL THEN 1 ELSE 0 END) ORDER BY totalTime ) END) totalRank
,totaltime - min(totaltime) over() diff
FROM results
ORDER BY -totalRank DESC;
Serg的答案是正確的。 我將其寫為:
SELECT id, name, totalTime,
(CASE WHEN totalTime IS NOT NULL
THEN RANK() OVER (PARTITION BY (totalTime IS NULL) ORDER BY totalTime)
END) as totalRank,
totaltime - MIN(totaltime) OVER() as diff
FROM results
ORDER BY (totalTime IS NOT NULL) DESC, totalRank;
不同之處在於:
PARTITION BY
。 您使用CASE
,但是MySQL方便地將布爾值視為“真實”值。 ORDER BY
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.