如何检索表中的最大值及其对应的日期

Mr.*_*ist 4 sql-server query max

我试图弄清楚如何从数据集中检索最小/最大值和最小/最大日期,以及每个最小/最大值对应的日期值。

示例数据

CREATE TABLE mytable
    ([ID] int, [TEMP] FLOAT, [DATE] DATE)
;

INSERT INTO mytable
    ([ID], [TEMP], [DATE])
VALUES
    (8305,  16.38320208,  '03/22/2002'),
    (8305,  17.78320208,  '11/15/2010'),
    (8305,  16.06320208,  '03/11/2002'),
    (8305,  18.06320208,  '02/01/2007'),
    (2034,  5.2,  '03/12/1985'),
    (2034,  2.24,  '05/31/1991'),
    (2034,  6.91,  '09/15/1981'),
    (2034,  7.98,  '07/16/1980'),
    (2034,  10.03,  '03/21/1979'),
    (2034,  6.85,  '11/19/1982')
;
Run Code Online (Sandbox Code Playgroud)

查询TEMPDATE列的最小值/最大值:

SELECT ID,
    COUNT(TEMP) AS COUNT,
    MAX(TEMP) AS MAXTEMP,
    MAX(DATE) AS MAXDATE
FROM mytable
GROUP BY ID;
Run Code Online (Sandbox Code Playgroud)

检索这个:

|   ID | COUNT |     MAXTEMP |    MAXDATE |
|------|-------|-------------|------------|
| 2034 |     6 |       10.03 | 1991-05-31 |
| 8305 |     4 | 18.06320208 | 2010-11-15 |
Run Code Online (Sandbox Code Playgroud)

但我想弄清楚如何检索它:

|   ID | COUNT |     MAXTEMP |MAXTEMPDATE |    MAXDATE|
| 2034 |     6 |       10.03 | 1979-03-21 |1991-05-31 |
| 8305 |     4 | 18.06320208 | 2007-02-01 |2010-11-15 |
Run Code Online (Sandbox Code Playgroud)

Ron*_*ldo 9

您可以使用公用表表达式 (CTE)ROW_NUMBER()来实现它:

;WITH cte AS
(
   SELECT *,
         ROW_NUMBER() OVER (PARTITION BY ID ORDER BY [TEMP] DESC) AS rn
   FROM mytable
)
SELECT cte.ID, 
    COUNT(*) AS COUNT, 
    cte.TEMP AS MAXTEMP, 
    cte.DATE AS MAXTEMPDATE,
    MAX(mt.DATE) AS MAXDATE
FROM cte
    INNER JOIN mytable mt ON cte.ID = mt.ID
WHERE rn = 1
GROUP BY cte.ID, 
    cte.TEMP, 
    cte.DATE;
Run Code Online (Sandbox Code Playgroud)


Mar*_*ith 6

一种可能更有效但更晦涩的方法是使用原始值提取所需的值group by

\n
SELECT ID,\n       COUNT = COUNT(TEMP),\n       MAXTEMP = MAX(TEMP),\n       MAXTEMPDATE = CAST(RIGHT(MAX(FORMAT(CAST([TEMP] + 500 AS DECIMAL(15, 10)), \'00000.0000000000\')\n                                    + FORMAT([DATE], \'yyyy-MM-dd\')), 10) AS DATE),\n       MAXDATE = MAX(DATE)\nFROM   mytable\nGROUP  BY ID; \n
Run Code Online (Sandbox Code Playgroud)\n

因为温度可能是负数,所以首先将它们全部增加 500,所以我不必担心负数(绝对零是 \xe2\x88\x92273.15 \xc2\xb0C/\xe2\x88\x92459.67 \xc2 \xb0F)。调整后的值除了由 之外从未使用过,MAX因此无需在任何地方反转它。

\n

然后,它将结果转换为 16 个字符的字符串,其中前 5 个字符保留为整数部分,最后 10 个字符保留为小数部分(两边根据需要用零填充)。这意味着值的字典排序将与数字排序匹配。

\n

最后,日期被添加到它的末尾 -MAX找到并从连接字符串中的已知位置检索日期。

\n

mytable(ID) INCLUDE (TEMP, DATE)如果你在执行计划上有一个索引,那么这是非常有效的。

\n

在此输入图像描述

\n
\n

至于为什么负值会在这里出现潜在的问题,这是因为我们必须确保字符串表示的排序方式与数字表示的排序方式完全相同。我的第一个想法是有一个表示符号的前导字符,以便首先对负值进行排序。下一个问题是-12高于 ,-20但字符串表示形式的00020排序会高于00012。对温度所保持的值域应用合理的偏移量可以让我避免这一切。还应用一个CHECK约束以确保数据中不存在无意义的温度值。

\n