sql - 获取与 SQL Server 2008 中一列的 MIN 和 MAX 值对应的其他列

标签 sql sql-server max min

我遇到一种情况,我需要获取列的 min() 和 max() 以及与 min() 和 max() 函数对应的另一列。我尝试过使用 INNER JOIN 进行查询,使用 min() 或 max() 时成功。当两者都使用时,不会返回任何内容。

SELECT A.IslandCode, CONVERT(DATE, A.LogTime)LogTime
, MN.Demand MinDemand, MN.TIME MinDemandAt
FROM 
(
    SELECT IslandCode, CONVERT(DATE, LogTime) LogTime, SUM(KiloWatt) Demand
    FROM ph_MachineDailyReadings 
    WHERE IslandCode = 1 AND CONVERT(DATE, LogTime) = '2013-08-13'
    GROUP BY IslandCode, LogTime
) A
INNER JOIN 
(
    SELECT TOP 1 IslandCode, CONVERT(DATE, LogTime) LogTime, SUM(KiloWatt) Demand, 
    STR(DATEPART(HOUR, LogTime)) + ':' + LTRIM(STR(DATEPART(MINUTE, LogTime))) TIME
    FROM ph_MachineDailyReadings 
    WHERE IslandCode = 1 AND CONVERT(DATE, LogTime) = '2013-08-13'
    GROUP BY IslandCode, LogTime
    ORDER BY Demand
) MN
ON A.IslandCode = MN.IslandCode AND A.LogTime = MN.LogTime AND A.Demand = MN.Demand

上面的查询返回以下结果,这是正确的

IslandCode  LogTime     MinDemand       MinDemandAt
1           2013-08-13  698         13:0

查询 max()

SELECT A.IslandCode, CONVERT(DATE, A.LogTime)LogTime
, MX.Demand MaxDemand, MX.TIME MaxDemandAt
FROM 
(
    SELECT IslandCode, CONVERT(DATE, LogTime) LogTime, SUM(KiloWatt) Demand
    FROM ph_MachineDailyReadings 
    WHERE IslandCode = 1 AND CONVERT(DATE, LogTime) = '2013-08-13'
    GROUP BY IslandCode, LogTime
) A
INNER JOIN
(
    SELECT TOP 1 IslandCode, CONVERT(DATE, LogTime) LogTime, SUM(KiloWatt) Demand, 
    STR(DATEPART(HOUR, LogTime)) + ':' + LTRIM(STR(DATEPART(MINUTE, LogTime))) TIME
    FROM ph_MachineDailyReadings 
    WHERE IslandCode = 1 AND CONVERT(DATE, LogTime) = '2013-08-13'
    GROUP BY IslandCode, LogTime
    ORDER BY Demand DESC
) MX
ON A.IslandCode = MX.IslandCode AND A.LogTime = MX.LogTime AND A.Demand = MX.Demand

返回,这也是正确的

IslandCode  LogTime       MaxDemand     MaxDemandAt
1           2013-08-13  1463            20:0

但是当两个查询在同一个查询中使用时,不返回任何内容

SELECT A.IslandCode, CONVERT(DATE, A.LogTime)LogTime
, MX.Demand MaxDemand, MX.TIME MaxDemandAt
, MN.Demand MinDemand, MN.TIME MinDemandAt
FROM 
(
    SELECT IslandCode, CONVERT(DATE, LogTime) LogTime, SUM(KiloWatt) Demand
    FROM ph_MachineDailyReadings 
    WHERE IslandCode = 1 AND CONVERT(DATE, LogTime) = '2013-08-13'
    GROUP BY IslandCode, LogTime
) A
INNER JOIN
(
    SELECT TOP 1 IslandCode, CONVERT(DATE, LogTime) LogTime, SUM(KiloWatt) Demand, 
    STR(DATEPART(HOUR, LogTime)) + ':' + LTRIM(STR(DATEPART(MINUTE, LogTime))) TIME
    FROM ph_MachineDailyReadings 
    WHERE IslandCode = 1 AND CONVERT(DATE, LogTime) = '2013-08-13'
    GROUP BY IslandCode, LogTime
    ORDER BY Demand DESC
) MX
ON A.IslandCode = MX.IslandCode AND A.LogTime = MX.LogTime AND A.Demand = MX.Demand
INNER JOIN 
(
    SELECT TOP 1 IslandCode, CONVERT(DATE, LogTime) LogTime, SUM(KiloWatt) Demand, 
    STR(DATEPART(HOUR, LogTime)) + ':' + LTRIM(STR(DATEPART(MINUTE, LogTime))) TIME
    FROM ph_MachineDailyReadings 
    WHERE IslandCode = 1 AND CONVERT(DATE, LogTime) = '2013-08-13'
    GROUP BY IslandCode, LogTime
    ORDER BY Demand
) MN
ON A.IslandCode = MN.IslandCode AND A.LogTime = MN.LogTime AND A.Demand = MN.Demand

预期结果

IslandCode   LogTime     MinDemand  MinDemandAt   MaxDemand   MaxDemandAt
    1       2013-08-13  1463        20:0        698      13:0

我可以在单个查询中获得此结果还是需要采用基于存储过程的解决方案?

提前致谢

最佳答案

您可以使用分析函数来做到这一点:

WITH Data AS
(   SELECT  IslandCode, 
            LogDate = CAST(LogTime AS DATE),
            LogTime, 
            Demand = SUM(KiloWatt) ,
            RowNumAsc = ROW_NUMBER() OVER (PARTITION BY IslandCode, CAST(LogTime AS DATE) ORDER BY SUM(Kilowatt)),
            RowNumDesc = ROW_NUMBER() OVER (PARTITION BY IslandCode, CAST(LogTime AS DATE) ORDER BY SUM(Kilowatt) DESC) 
    FROM    ph_MachineDailyReadings 
    WHERE   IslandCode = 1 
    AND     CAST(LogTime AS DATE) = '20130813'
    GROUP BY IslandCode, LogTime
)
SELECT  ma.IslandCode,
        LogTime = ma.LogDate,
        MinDemand = mi.Demand,
        MinDemandAt = CAST(mi.LogTime AS TIME),
        MaxDemand = ma.Demand,
        MaxDemandAt = CAST(ma.LogTime AS TIME)
FROM    Data mi
        INNER JOIN Data ma
            ON ma.IslandCode = mi.IslandCode
            AND ma.LogDate = mi.LogDate
WHERE   mi.RowNumAsc = 1
AND     ma.RowNumDesc = 1;

<强> Example on SQL Fiddle

编辑

这不需要参数,如果省略 WHERE 子句,如下所示,它将返回每个日期的每个岛屿代码的最小值和最大值:

WITH Data AS
(   SELECT  IslandCode, 
            LogDate = CAST(LogTime AS DATE),
            LogTime, 
            Demand = SUM(KiloWatt) ,
            RowNumAsc = ROW_NUMBER() OVER (PARTITION BY IslandCode, CAST(LogTime AS DATE) ORDER BY SUM(Kilowatt)),
            RowNumDesc = ROW_NUMBER() OVER (PARTITION BY IslandCode, CAST(LogTime AS DATE) ORDER BY SUM(Kilowatt) DESC) 
    FROM    ph_MachineDailyReadings 
    GROUP BY IslandCode, LogTime
)
SELECT  ma.IslandCode,
        LogTime = ma.LogDate,
        MinDemand = mi.Demand,
        MinDemandAt = CAST(mi.LogTime AS TIME),
        MaxDemand = ma.Demand,
        MaxDemandAt = CAST(ma.LogTime AS TIME)
FROM    Data mi
        INNER JOIN Data ma
            ON ma.IslandCode = mi.IslandCode
            AND ma.LogDate = mi.LogDate
WHERE   mi.RowNumAsc = 1
AND     ma.RowNumDesc = 1;

<强> Example on SQL Fiddle

最后一点,我已将您的 logTime 采用 TIME 格式,因为这似乎比 VARCHAR 格式更有用,如果您确实需要 VARCHAR 格式,您可以使用:

CONVERT(VARCHAR(10), ma.LogTime, 8)

关于sql - 获取与 SQL Server 2008 中一列的 MIN 和 MAX 值对应的其他列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18273353/

相关文章:

Mysql存储过程不是有吗?

java - java 求数组第二个和第三个最大元素

sql - 如何在 SQL Server 中实现多语言内容的全文搜索

mysql - 仅当该组连接列中存在特定值时,如何在 MySql 中进行组连接

mysql - SQL - 按条目 X 彼此间隔的时间对表进行分组

C# 更改表并以编程方式添加列 ASP.Net 和 SQL Server

sql - 创建表后立即使用表 : object does not exist

sql-server - 估计全文索引大小

r - 在 R 中使用 argmax 或更简单的东西

python - Python 中的最小或最大赋值运算符