从每组中仅选择第一行

时间:2019-07-02 05:20:27

标签: sql sql-server tsql

我对下表有疑问。我只需要选择最大的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_KEY ?基本上,我只需要从每个集合中选择满足条件 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 个答案:

答案 0 :(得分:2)

我们可以在此处使用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

Demo

这将选择最大USCO_DFR值与USCO_AHO的值相同的同一记录的所有用户记录。

答案 1 :(得分:1)

您可以将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

答案 2 :(得分: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', '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

答案 3 :(得分:1)

打破分析功能可能有点矫kill过正,但是它们非常好用……

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 |

答案 4 :(得分: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')

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

IMAGE LINK

答案 5 :(得分:0)

尝试一下

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 

答案 6 :(得分:0)

在简单的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'

Working demo on db<>fiddle