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.