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

发布于 2024-08-14 12:03:51 字数 871 浏览 4 评论 0原文

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

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 字段是唯一字段和关键字段,我想要一个查询来输出每个值的最小和最大日期时间,以便它将显示如下所示的内容:

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。

谢谢。

I have a table structure similar to the following example:

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

With DateTime field being the unqiue and key field, I want a query to output min and max date time for each values so that it will show something like below:

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 

If there are multiple rows with the same min/max value, then it should get the latest one.

With Inner Join on a field, I know to get the details of min/max row for a field, but only way I can think getting everything in one query is to union them all. I think there might be a better solution. Any help is appreciated.

I am using SQL Server 2008.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

缺⑴份安定 2024-08-21 12:03:51
  • 逆透视到有用的行(“标准化”)
  • 计算出每种类型的 MIN/MAX,如果存在关系,则允许 MAX 日期时间
  • 提取 MIN/MAX 值

嘿,请先...

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];
  • Unpivot into useful rows ("normalise")
  • Work out MIN/MAX per Type, allowing for MAX datetime if ties
  • Extract MIN/MAX values

Hey 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];
我不在是我 2024-08-21 12:03:51

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

其效果如下:

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

You can get both max and min values in a single query. To get max/min datetime you will have to join the max/min query back to the table (once per every value)

something to the effect of:

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
兔小萌 2024-08-21 12:03:51

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

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 |
+-----------+-----------+-----------+-----------+

Not sure if this is what you are after, but it seems to solve this basic case:

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 |
+-----------+-----------+-----------+-----------+
┊风居住的梦幻卍 2024-08-21 12:03:51

我将从标准化您的数据开始。由于 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 搜索该类型的最小值,然后第二个交叉应用搜索最大值。

I'd start with normalizing your data. Since V2 does not depend on V1, they should not be in the same row. Here's a normalizing query:

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 that, what remains is the "selecting records holding group-wise maximum with tie" problem. One way to solve that is:

;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

The dd query returns the Types (V1, V2, ...) The first cross apply searches for the minimums for that type, and the second cross apply searches for the maximums.

寂寞清仓 2024-08-21 12:03:51

我读了这个问题并想:我宁愿用 php 而不是 sql 来做到这一点。

然后我读了答案,我想:我真的宁愿用 php 而不是 sql 来做这件事。

i read the question and thought: i'd rather do that in php than sql.

then i read the answers and i thought: i'd really rather do that in php than sql.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文