Рейтинг T-SQL с первым, минимальным, максимальным, последним - PullRequest
1 голос
/ 08 ноября 2010

HI!У меня есть таблица SQL Server, которая содержит следующие поля:

DateTime DATETIME
Price FLOAT

Таблица имеет уникальный ключ DateTime.Я хотел бы написать запрос, который возвращает данные в виде 20-рядных блоков, возвращая ПЕРВАЯ, МАКС., МИН. И ПОСЛЕДНЯЯ цена для каждого набора из 20 строк....

Ответы [ 3 ]

1 голос
/ 08 ноября 2010

Я считаю, что ваша первая группа содержит только 19 строк, а не 20 (потому что номера строк начинаются с 1, а не с 0). Это легко исправить - просто вычтите 1 из ROW_NUMBER ().

Ниже я также предоставляю альтернативное решение, которое, вероятно, будет значительно более эффективным (поскольку у него нет подзапросов для реализации в виде вложенных циклов), и оно также может быть более управляемым.

Примечание. Если количество строк в «ценах» не делится точно на 20, то решение Сэма и моего получит первые, минимальные, максимальные и последние цены для одной группы, содержащей менее 20 наименований - эта группа содержит самые последние предметы. (Хорошая идея - протестировать подобный запрос, используя количество строк, не делимое на 20 ...)

DECLARE @groupsize INT = 20;
WITH PricesWithRkGp(PurchaseDate,Price,RkUp,RkDn,Gp) AS (
  SELECT
    PurchaseDate,
    Price,
    -1+ROW_NUMBER() OVER (ORDER BY PurchaseDate),
    -1+ROW_NUMBER() OVER (ORDER BY PurchaseDate DESC),
    (-1+ROW_NUMBER() OVER (ORDER BY PurchaseDate)) / @groupsize
  FROM Prices
)
  SELECT
    MIN(Price) AS MinPrice,
    MAX(Price) AS MaxPrice,
    Gp,
    MAX(CASE WHEN RkUp%@groupsize = 0 THEN Price ELSE NULL END) AS FirstPrice,
    MAX(CASE WHEN RkUp%@groupsize = @groupsize - 1 OR RkDn = 0 THEN Price ELSE NULL END) AS LastPrice
  FROM PricesWithRkGp
  GROUP BY Gp
  ORDER BY Gp;
0 голосов
/ 08 ноября 2010

Вы можете сделать это, используя функцию ROW_NUMBER CTE.Вот код с деталями:

http://blog.sqlauthority.com/2007/06/11/sql-server-2005-t-sql-paging-query-technique-comparison-over-and-row_number-cte-vs-derived-table/

0 голосов
/ 08 ноября 2010

Вы имеете в виду что-то вроде этого:

select 
    *,
    (select Price from Prices where PurchaseDate = [Start]) as [First Price],
    (select Price from Prices where PurchaseDate = [Finish]) as [Last Price]
from
(
    select 
        MIN(PurchaseDate) as [Start], 
        MAX(PurchaseDate) as [Finish], 
        MIN(Price) as [Min Price], 
        MAX(Price) as [Max Price], 
        AVG(Price) as [Average Price]
        from 
    (
        select (ROW_NUMBER() OVER (ORDER BY PurchaseDate)) / 20 as [Seq], *
        from Prices
    ) as X 
    group by X.Seq
) as Y

Обратите внимание, я использовал следующее для генерации данных:

create table Prices (
PurchaseDate DATETIME primary key,
Price FLOAT
)

go

declare @records int
declare @date datetime 
declare @price float

set @records = 1000

while @records > 0 
begin 

    set @date = GETDATE() - cast((RAND() * 10000) as int)
    set @price = RAND() * 10000     

    if not exists(select 1 from Prices where PurchaseDate = @date) 
    begin 
        insert Prices values (@date, @price) 
        set @records = @records - 1
    end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...