簡體   English   中英

計算最小值與每行值之間的差

[英]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;

不同之處在於:

  1. 通過簡化PARTITION BY 您使用CASE ,但是MySQL方便地將布爾值視為“真實”值。
  2. 以更直觀的方式表達ORDER BY

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM