2

列の min() と max() の両方と、min() および max() 関数に対応するもう 1 つの列を取得する必要がある状況があります。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

この結果を単一のクエリで取得できますか、それともストアド プロシージャ ベースのソリューションを使用する必要がありますか?

前もって感謝します

4

2 に答える 2

2

これは、分析関数を使用して行うことができます。

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;

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;

SQL Fiddle の例

最後に、logTime を TIME 形式にしました。これは、VARCHAR 形式で必要な場合は、VARCHAR 形式よりも使いやすいように思われるためです。

CONVERT(VARCHAR(10), ma.LogTime, 8)
于 2013-08-16T12:52:54.913 に答える
0

2回目の参加は必要ないと思います。だけでこれを行うことができますunion all

(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
) union all
(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
)
于 2013-08-16T12:58:50.360 に答える