Запрос T-SQL OVER / PARTITION BY с условием - PullRequest
0 голосов
/ 30 августа 2018

Я борюсь с запросом SQL, и хотя я просмотрел много похожих ответов, ни один из них не вполне соответствовал моей ситуации. У меня есть набор данных, как показано ниже:

Date1       Amount 1    Index   Date2               Type Supplier
31/03/2018  410000.00   17      16/04/2018 06:27    102  A
31/03/2018  410000.00   17      16/04/2018 06:31    102  B
31/03/2018  400000.00   2       16/04/2018 06:37    102  A
31/03/2018  400000.00   2       16/04/2018 06:38    102  B
30/06/2018  0           20      04/07/2018 08:23    202  A
30/06/2018  0           20      04/07/2018 08:23    202  B
30/06/2018  412000.00   20      06/07/2018 12:46    102  A
30/06/2018  412000.00   20      06/07/2018 12:47    102  B
30/06/2018  442000.00   100     16/07/2018 06:27    102  A
30/06/2018  442000.00   100     16/07/2018 06:31    102  B

Для каждой даты1, где есть несколько строк с одним и тем же типом, я хочу только те строки, индекс которых соответствует индексу максимальной даты2, поэтому я хочу получить следующие выходные данные:

Date1       Amount 1    Index   Date2               Type Supplier
31/03/2018  400000.00   2       16/04/2018 06:37    102  A
31/03/2018  400000.00   2       16/04/2018 06:38    102  B
30/06/2018  0           20      04/07/2018 08:23    202  A
30/06/2018  0           20      04/07/2018 08:23    202  B
30/06/2018  442000.00   100     16/07/2018 06:27    102  A
30/06/2018  442000.00   100     16/07/2018 06:31    102  B

Я чувствую, что это возможно с некоторой формой MAX () OVER (PARTITION BY), но я не могу понять, как это сделать.

Ответы [ 6 ]

0 голосов
/ 30 августа 2018

Использование LAST_VALUE (Transact-SQL) аналитическая функция вместе с подзапросом.

Приведенный ниже рабочий пример относится к Oracle (я предпочитаю Oracle, потому что у меня всегда есть проблема с преобразованием дат на SQLServer), но идея запроса та же, синтаксис также тот же:

Демо: http://www.sqlfiddle.com/#!4/004ce7/19

SELECT * FROM (
   SELECT t.* ,
     last_value( "INDEX" ) OVER 
        ( partition by date1, "TYPE" order by date2
          ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) xx
   FROM table1 t
) x
WHERE xx = "INDEX"
ORDER BY date1;

|                DATE1 | AMOUNT1 | INDEX |                 DATE2 | TYPE | SUPPLIER |  XX |
|----------------------|---------|-------|-----------------------|------|----------|-----|
| 2018-03-31T00:00:00Z |  400000 |     2 | 2018-04-16 06:37:00.0 |  102 |        A |   2 |
| 2018-03-31T00:00:00Z |  400000 |     2 | 2018-04-16 06:38:00.0 |  102 |        B |   2 |
| 2018-06-30T00:00:00Z |  442000 |   100 | 2018-07-16 06:27:00.0 |  102 |        A | 100 |
| 2018-06-30T00:00:00Z |  442000 |   100 | 2018-07-16 06:31:00.0 |  102 |        B | 100 |
| 2018-06-30T00:00:00Z |       0 |    20 | 2018-07-04 08:23:00.0 |  202 |        B |  20 |
| 2018-06-30T00:00:00Z |       0 |    20 | 2018-07-04 08:23:00.0 |  202 |        A |  20 |
0 голосов
/ 30 августа 2018

Вы можете использовать коррелированный подзапрос:

select t.*
from table t
where Index = (select top (1) t1.Index
               from table t1
               where t1.Date1 = t.Date1 and t1.type = t.type
               order by t1.date2 desc
              );   
0 голосов
/ 30 августа 2018

Подзапрос сортирует ваши данные так, чтобы строка, управляющая индексом, всегда была row_no единица для каждой группировки даты и типа. Внешний запрос возвращает все строки, которые имеют одинаковую комбинацию date1, type, index, но игнорирует остальные

Select *
From Data D
    inner join SortedData S on S.Date1 = A.Date1 
          and S.Type = A.Type 
          and S.RowNo = 1 
          and D.Index = A.index

(Select Date1, Type, Index, row_Number() over (Partition by Date1, Type ORDER BY Date2 DESC) as RowNo From Data) SortedData
0 голосов
/ 30 августа 2018

попробуйте

;WITH CTE
AS
(
    SELECT
        *,
        MxDt =ROW_NUMBER() OVER(PARTITION BY Date1,[Type] ORDER BY Date2 DESC)
        FROM YourTableName
)
SELECT
    *
    FROM CTE C1
        WHERE EXISTS
        (
            SELECT
                1
                FROM CTE C2
                    WHERE [Index] = C1.[Index]
                        AND [Type]= C1.[Type]
                        AND C2.MxDt =1
        )
0 голосов
/ 30 августа 2018

Использовать row_number ()

SELECT [Date1],[Amount 1],[Index],[Date2],[Type],[Supplier]
FROM (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY [Date1] ORDER BY [Date2] DESC) AS rn
    FROM tablename
) a
WHERE a.rn in( 1,2)
0 голосов
/ 30 августа 2018

Я думаю, это то, что вы хотите. Обратите внимание, что использование ROW_NUMBER вместо RANK - RANK приведет к нескольким значениям 1, где Date2 - то же самое, ROW_NUMBER - к уникальным инкрементным значениям для rn:

SELECT
    [Date1],
    [Amount 1],
    [Index],
    [Date2],
    [Type],
    [Supplier]
FROM my_table
INNER JOIN (
    SELECT
        [Index],
        [Type],
        ROW_NUMBER() OVER (PARTITION BY [Date1], [Type] ORDER BY [Date2] DESC) AS rn
    FROM my_table
) AS subquery
    ON subquery.rn = 1
    AND subquery.[Index] = my_table.[Index]
    AND subquery.[Type] = my_table.[Type]
...