Выберите только верхний ряд из каждого набора - PullRequest
0 голосов
/ 02 июля 2019

У меня проблема с таблицей ниже. Я должен выбрать только пользователей с наибольшим USCO_DFR и USCO_AHO = '1' . Итак, из приведенного ниже примера:

+----------+-------------------------+----------+
| USER_KEY |        USCO_DFR         | USCO_AHO |
+----------+-------------------------+----------+
|        1 | 2018-06-01 00:00:00.000 | NULL     |
|        1 | 2018-03-05 00:00:00.000 | 1        |
|        1 | 2018-02-10 00:00:00.000 | NULL     |
|        2 | 2018-07-10 00:00:00.000 | 1        |
|        2 | 2018-04-05 00:00:00.000 | NULL     |
|        2 | 2018-01-15 00:00:00.000 | NULL     |
|        3 | 2018-09-10 00:00:00.000 | 1        |
|        3 | 2018-05-05 00:00:00.000 | NULL     |
|        3 | 2018-04-15 00:00:00.000 | NULL     |
+----------+-------------------------+----------+

только USER_KEY = 2,3 .

Ожидаемый результат:

+----------+-------------------------+----------+
| USER_KEY |        USCO_DFR         | USCO_AHO |
+----------+-------------------------+----------+
|        2 | 2018-07-10 00:00:00.000 |        1 |
|        3 | 2018-09-10 00:00:00.000 |        1 |
+----------+-------------------------+----------+

Этот запрос сортирует результаты:

SELECT * FROM @BAUSCO ORDER BY USER_KEY, USCO_DFR DESC

но я не знаю, как выбрать эти USER_KEYs из результата? В основном я должен выбрать только верхнюю строку из каждого набора, где это удовлетворяет условию USCO_AHO = '1' .

DECLARE @BAUSCO TABLE
(
    USER_KEY INT,
    USCO_DFR DATETIME,
    USCO_AHO CHAR(1)
)

INSERT @BAUSCO(USER_KEY, USCO_DFR, USCO_AHO)
VALUES (1, '2018-02-10', NULL),
(1, '2018-03-05', '1'),
(1, '2018-06-01', NULL),

(2, '2018-01-15', NULL),
(2, '2018-04-05', NULL),
(2, '2018-07-10', '1'),

(3, '2018-04-15', NULL),
(3, '2018-05-05', NULL),
(3, '2018-09-10', '1')

Ответы [ 7 ]

2 голосов
/ 02 июля 2019

Мы можем использовать ROW_NUMBER здесь, чтобы указать самую большую запись USCO_DFR для каждого пользователя:

WITH cte AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY USER_KEY ORDER BY USCO_DFR DESC) rn
    FROM @BAUSCO
)

SELECT USER_KEY, USCO_DFR, USCO_AHO
FROM cte
WHERE USCO_AHO = 1 and rn = 1;

enter image description here

Демо

При этом будут выбраны все пользовательские записи, наибольшее значение USCO_DFR которых совпадает с той же записью, для которой USCO_AHO имеет значение 1.

1 голос
/ 02 июля 2019
DECLARE @BAUSCO TABLE
(
    USER_KEY INT,
    USCO_DFR DATETIME,
    USCO_AHO CHAR(1)
)

INSERT @BAUSCO(USER_KEY, USCO_DFR, USCO_AHO)
VALUES (1, '2018-02-10', NULL),
(1, '2018-03-05', '1'),
(1, '2018-06-01', NULL),

(2, '2018-01-15', NULL),
(2, '2018-04-05', NULL),
(2, '2018-07-10', '1'),

(3, '2018-04-15', NULL),
(3, '2018-05-05', NULL),
(3, '2018-09-10', '1')

select * from @BAUSCO a
where USCO_DFR=(select MAX(USCO_DFR) from @BAUSCO b where a.USER_KEY=b.USER_KEY )
    and USCO_AHO=1

ССЫЛКА ИЗОБРАЖЕНИЯ

1 голос
/ 02 июля 2019

Может быть, немного излишне разбивать аналитические функции, но они чертовски удобны ...

SELECT * FROM
(SELECT
    *,
    MAX(USCO_DFR) OVER (PARTITION BY USER_KEY) AS MAX_DFR
  FROM
    @BAUSCO
) T
WHERE
  T.USCO_AHO = '1' 
  AND T.USCO_DFR = T.MAX_DFR

Результаты:

| USER_KEY |             USCO_DFR | USCO_AHO |              MAX_DFR |
|----------|----------------------|----------|----------------------|
|        2 | 2018-07-10T00:00:00Z |        1 | 2018-07-10T00:00:00Z |
|        3 | 2018-09-10T00:00:00Z |        1 | 2018-09-10T00:00:00Z |
1 голос
/ 02 июля 2019

Следующий запрос должен делать то, что вы хотите:

DECLARE @BAUSCO TABLE
(
    USER_KEY INT,
    USCO_DFR DATETIME,
    USCO_AHO CHAR(1)
)

INSERT @BAUSCO(USER_KEY, USCO_DFR, USCO_AHO)
VALUES (1, '2018-02-10', NULL),
(1, '2018-03-05', '1'),
(1, '2018-06-01', NULL),

(2, '2018-01-15', '1'),
(2, '2018-04-05', NULL),
(2, '2018-07-10', '1'),

(3, '2018-04-15', '1'),
(3, '2018-05-05', NULL),
(3, '2018-09-10', '1')

SELECT USER_KEY, USCO_DFR, USCO_AHO FROM (
SELECT USER_KEY
    ,USCO_DFR
    ,USCO_AHO
    ,ROW_NUMBER() OVER (PARTITION BY USER_KEY ORDER BY (SELECT 1)) AS RNO
FROM @BAUSCO ) A
WHERE A.USCO_AHO = A.RNO AND A.USCO_AHO = 1

Результат, как показано ниже,

USER_KEY    USCO_DFR                  USCO_AHO
2           2018-01-15 00:00:00.000   1
3           2018-04-15 00:00:00.000   1
1 голос
/ 02 июля 2019

вы можете использовать ROW_NUMBER с CTE

;with cte as
(
select ROW_NUMBER()  over (partition by USER_KEY order by USCO_DFR desc) AS ROWNUM,*
from 
@BAUSCO
)
select USER_KEY, USCO_DFR, USCO_AHO from cte where ROWNUM=1 and USCO_AHO =1
0 голосов
/ 02 июля 2019

В простом SQL, используя GROUP BY с подзапросом, вы можете получить ожидаемый результат:

SELECT Q.USER_KEY, Q.USCO_DFR, B.USCO_AHO
FROM (
    SELECT USER_KEY, MAX(USCO_DFR) AS USCO_DFR
    FROM @BAUSCO
    GROUP BY USER_KEY
) Q 
JOIN @BAUSCO B ON B.USER_KEY = Q.USER_KEY AND B.USCO_DFR = Q.USCO_DFR
WHERE B.USCO_AHO = '1'

Рабочая демонстрация на db <> fiddle

0 голосов
/ 02 июля 2019

Попробуйте это

SELECT A.* FROM @BAUSCO A INNER JOIN
(
     SELECT USER_KEY, Max(USCO_DFR) MaxUSCO_DFR
     FROM @BAUSCO
     GROUP BY USER_KEY
) B
ON A.USER_KEY = B.USER_KEY AND A.USCO_DFR = B.MaxUSCO_DFR
WHERE A.USCO_AHO = 1 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...