选择每组的第一行

mez*_*hic 6 sql sql-server sql-server-2008

我有一个有三列的表:A,B,C.

价值观是:

+---+-----+----+
| A |  B  | C  |
+---+-----+----+
| 1 | -10 |  5 |
| 1 |   0 |  5 |
| 1 |  10 |  5 |
| 2 |  10 | 12 |
| 2 |   0 | 12 |
| 3 | -10 | 14 |
| 4 |   0 |  8 |
| 4 |  10 |  8 |
| 5 |   0 |  6 |
| 5 |   1 |  6 |
| 5 |  -5 |  6 |
+---+-----+----+
Run Code Online (Sandbox Code Playgroud)

如果我首先按列排序数据A,然后是列B,然后是列C(尽管我确实使C每列A值的所有列值相同),我如何选择每列的"第一行" A

所以,这应该导致:

+---+-----+----+
| A |  B  | C  |
+---+-----+----+
| 1 | -10 |  5 |
| 2 |   0 | 12 |
| 3 | -10 | 14 |
| 4 |   0 |  8 |
| 5 |  -5 |  6 |
+---+-----+----+
Run Code Online (Sandbox Code Playgroud)

Qua*_*noi 16

SELECT  a, b, c
FROM    (
        SELECT  *, ROW_NUMBER() OVER (PARTITION BY a ORDER BY b, c) rn
        FROM    mytable
        ) q
WHERE   rn = 1
ORDER BY
        a
Run Code Online (Sandbox Code Playgroud)

要么

SELECT  mi.*
FROM    (
        SELECT  DISTINCT  a
        FROM    mytable
        ) md
CROSS APPLY
        (
        SELECT  TOP 1 *
        FROM    mytable mi
        WHERE   mi.a = md.a
        ORDER BY
                b, c
        ) mi
ORDER BY
        a
Run Code Online (Sandbox Code Playgroud)

创建复合索引(a, b, c)以使查询更快地运行.

哪一个更有效取决于您的数据分布.

如果a每个中都有很少的不同值但很多记录a,那么第二个查询会更好.

您可以通过创建索引视图来进一步改进它:

CREATE VIEW v_mytable_da
WITH   SCHEMABINDING
AS
       SELECT  a, COUNT_BIG(*) cnt
       FROM    dbo.mytable
       GROUP BY
               a

GO

CREATE UNIQUE CLUSTERED INDEX
       pk_vmytableda_a
ON     v_mytable_da (a)

GO

SELECT  mi.*
FROM    v_mytable_da md
CROSS APPLY
        (
        SELECT  TOP 1 *
        FROM    mytable mi
        WHERE   mi.a = md.a
        ORDER BY
                b, c
        ) mi
ORDER BY
        a
Run Code Online (Sandbox Code Playgroud)