简体   繁体   中英

SQL Find Values Where MIN in a GROUP BY

I am creating a summary-view of a table. I would like to retrieve the date where a field is at it's MAX/MIN, all grouped (it's a summary). I'm using this at the moment, and it works, but it is incredibly slow over many fields:

SELECT A.Timestamp, A.Date

-- FIND MAX VALUE
MAX(A.Field1) AS MaxDate,

-- FIND DATE AT MAX-VALUE
(SELECT Date
FROM MyTable
WHERE Field1 = MAX(A.Field1)
AND Timestamp = A.Timestamp
AND Date = A.Date)

-- DO THE SAME FOR MIN VALUE, MEDIAN VALUE, ETC, ETC

FROM MyTable AS A
GROUP BY A.Timestamp, A.Date

I do a similar operation on many fields. Can anyone please suggest a better way of doing this? Thanks

我认为索引可以解决您的性能问题:

create index idx_mytable_date_timestamp_field1 on mytable(date, timestamp, field1);

The index Gordon mentioned should cover your query and speed things up. There's nothing particularly wrong with the way you are doing it; but, I wanted to take a shot at getting the aggregates in one query.

I made a few assumptions about your schema, please let me know if I went astray. Here I use an indexer to sort all the values in asc & desc order, then use these two indices to find the min, max, and media values/dates.

note: be sure this handles ties as you need

if object_id('tempdb..#t') is not null 
    drop table #t;

create table #t ([pk] int, [Date] date, [Timestamp] time, Field1 decimal primary key(pk, [date]));
insert into #t
    values  (1, '01-01-2001', '13:00', 10),
            (1, '01-02-2001', '13:00', 20),
            (1, '01-03-2001', '13:00', 30),
            (1, '01-04-2001', '13:00', 40),
            (1, '01-05-2001', '13:00', 50),
            (1, '01-06-2001', '13:00', 50),
            --
            (2, '02-01-2001', '13:00', 10),
            (2, '02-02-2001', '13:00', 90),
            (2, '02-03-2001', '13:00', 70),
            (2, '02-04-2001', '13:00', 0),
            (2, '02-05-2001', '13:00', 33)



select  pk,
        [median] = min(case when Up in (Down, Down - 1, Down + 1) then Field1 else null end),
        [medianDate] = min(case when Up in (Down, Down - 1, Down + 1) then [Date] else null end),
        [minValue] = min(case when Up = 1 then Field1 else null end),
        [minDate] = min(case when Up = 1 then [Date] else null end),
        [maxValue] = min(case when Down = 1 then Field1 else null end),
        [maxDate] = min(case when Down = 1 then [Date] else null end)
from    (   select  pk,
                    Field1,
                    [Date],
                    row_number() over (partition by pk order by Field1 asc),
                    row_number() over (partition by pk order by Field1 desc) 
            from    #t
        ) d (pk, Field1, [Date], Up, Down)
group
by      pk;

Returns:

pk  median  medianDate  minValue    minDate     maxValue    maxDate
1   30      2001-01-03  10          2001-01-01  50          2001-01-05
2   33      2001-02-05  0           2001-02-04  90          2001-02-02

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM