查询以获取多个字段的最大/最小行详细信息

时间:2009-12-13 15:19:03

标签: sql sql-server tsql aggregate

我有一个类似于以下示例的表结构:

DateTime              V1    V2    V3    V4    
10/10/10 12:10:00     71    24    33    40
10/10/10 12:00:00     75    22    44    12
10/10/10 12:30:00     44    21    44    33
10/10/10 12:20:00     80    11    88    12

如果DateTime字段是unqiue和key字段,我想要一个查询输出每个值的最小和最大日期时间,以便它显示如下所示:

TYPE    MIN     MINDATETIME         MAX     MAXDATETIME 
V1      44      10/10/10 12:30:00   80      10/10/10 12:20:00 
V2      11      10/10/10 12:20:00   24      10/10/10 12:10:00 
V3      33      10/10/10 12:10:00   88      10/10/10 12:20:00 
V4      12      10/10/10 12:20:00   40      10/10/10 12:10:00 

如果有多行具有相同的最小/最大值,则应该获得最新的一行。

使用Inner Join在一个字段上,我知道要获取字段的最小/最大行的详细信息,但只有这样我才能认为在一个查询中获取所有内容是将它们全部合并。我认为可能有更好的解决方案。任何帮助表示赞赏。

我正在使用SQL Server 2008。

感谢。

5 个答案:

答案 0 :(得分:2)

  • 取消投入有用的行(“规范化”)
  • 根据类型计算出MIN / MAX,如果是
  • ,则允许MAX datetime
  • 提取MIN / MAX值

嘿presto ...

DECLARE @foo TABLE (
    DateTimeKey datetime NOT NULL,
    V1 int NOT NULL,
    V2 int NOT NULL,
    V3 int NOT NULL,
    V4 int NOT NULL
);

INSERT @foo (DateTimeKey, V1, V2, V3, V4)
SELECT '10/10/10 12:10:00',     71,    24,    33,    40 
UNION ALL SELECT '10/10/10 12:00:00',     75,    22,    44,    12 
UNION ALL SELECT '10/10/10 12:30:00',     44,    21,    44,    33 
UNION ALL SELECT '10/10/10 12:20:00',     80,    11,    88,    12;


WITH cTE AS 
(
    SELECT
        [Type], [Value], DateTimeKey,
        ROW_NUMBER() OVER (PARTITION BY [Type] ORDER BY [Value], DateTimeKey DESC) AS TypeRankMin, 
        ROW_NUMBER() OVER (PARTITION BY [Type] ORDER BY [Value] DESC, DateTimeKey DESC) AS TypeRankMax
    FROM
        (
        SELECT
            [Type], [Value], DateTimeKey
        FROM 
           (SELECT DateTimeKey, V1, V2, V3, V4 FROM @foo) p
           UNPIVOT
           ([Value] FOR [Type] IN (V1, V2, V3, V4)) AS unp
        ) bar
)
SELECT
    Mn.[Type], [MIN], MINDATETIME, [MAX], MAXDATETIME
FROM
    (
        SELECT 
            [Type], [Value] AS [MIN], DateTimeKey AS MINDATETIME
        FROM
            cTE
        WHERE
            TypeRankMin = 1
    ) Mn
    JOIN
    (
        SELECT 
            [Type], [Value] AS [MAX], DateTimeKey AS MAXDATETIME
        FROM
            cTE
        WHERE
            TypeRankMax = 1
    ) Mx ON Mn.[Type] = Mx.[Type];

答案 1 :(得分:0)

您可以在单个查询中同时获取最大值和最小值。要获得最大/最小日期时间,您必须将最大/最小查询连接回表(每个值一次)

产生影响的东西:

select values.*, mint.timestamp, maxt.timestamp from
    (select MIN(value) as minv, MAX(value) as maxv from table group by value) values,
    table mint,
    table maxt
where 
    mint.value = values.minv
    maxt.value = values.maxv

答案 2 :(得分:0)

不确定这是否是你所追求的,但它似乎解决了这个基本情况:

create table t(a int,b int);
insert into t(a,b) values(1,2),(2,3),(-1,-10);

select max(t1.a),min(t1.a),max(t2.b),min(t2.b) from t as t1,t as t2;
+-----------+-----------+-----------+-----------+
| max(t1.a) | min(t1.a) | max(t2.b) | min(t2.b) |
+-----------+-----------+-----------+-----------+
|         2 |        -1 |         3 |       -10 |
+-----------+-----------+-----------+-----------+

答案 3 :(得分:0)

我首先要规范化您的数据。由于V2不依赖于V1,因此它们不应位于同一行。这是一个规范化查询:

SELECT DateTime, 'V1' as Type, V1 as Value FROM @data
UNION ALL select DateTime, 'V2', V2 FROM @data
UNION ALL select DateTime, 'V3', V3 FROM @data
UNION ALL select DateTime, 'V4', V4 FROM @data

有了这个,剩下的就是“选择记录持有分组最大值并且有关系”的问题。解决这个问题的一种方法是:

;WITH normal AS (
    SELECT DateTime, 'V1' as Type, V1 as Value FROM @data
    UNION ALL select DateTime, 'V2', V2 FROM @data
    UNION ALL select DateTime, 'V3', V3 FROM @data
    UNION ALL select DateTime, 'V4', V4 FROM @data
)
SELECT *
FROM    (SELECT  DISTINCT Type FROM normal) dd
CROSS APPLY (
        SELECT   TOP 1 DateTime MINDATETIME, Value MIN
        FROM     normal di
        WHERE    di.Type = dd.Type
        ORDER BY Value, DateTime desc
        ) dimin
CROSS APPLY (
        SELECT   TOP 1 DateTime MAXDATETIME, Value MAX
        FROM     normal di
        WHERE    di.Type = dd.Type
        ORDER BY Value desc, DateTime desc
        ) dimax

dd查询返回类型(V1,V2,...)第一个cross apply搜索该类型的最小值,第二个cross apply搜索最大值。

答案 4 :(得分:0)

我读到了这个问题并且想到了:我宁愿在PHP中做这个而不是sql。

然后我读了答案,我想:我真的而不是在PHP中而不是sql。