如何仅为列的每个唯一值选择第一行

nui*_*it9 82 sql t-sql sql-server select unique

假设我有一个客户地址表:

CName           |   AddressLine
-------------------------------
John Smith      | 123 Nowheresville
Jane Doe        | 456 Evergreen Terrace
John Smith      | 999 Somewhereelse
Joe Bloggs      | 1 Second Ave
Run Code Online (Sandbox Code Playgroud)

在表中,像John Smith这样的客户可以拥有多个地址.我需要这个表的select查询只返回在'CName'中有重复项的第一行.对于这个表,它应该返回除第3个(或第1个)之外的所有行 - 这两个地址中的任何一个都可以,但只能返回一个.是否有一个关键字我可以根据服务器之前是否已经看过列值来添加到SELECT查询中进行过滤?

gbn*_*gbn 117

如果您说您不关心使用哪个地址,这是一个非常简单的答案.

SELECT
    CName, MIN(AddressLine)
FROM
    MyTable
GROUP BY
    CName
Run Code Online (Sandbox Code Playgroud)

如果你想要第一个根据,例如,"插入"列,那么它是一个不同的查询

SELECT
    M.CName, M.AddressLine,
FROM
    (
    SELECT
        CName, MIN(Inserted) AS First
    FROM
        MyTable
    GROUP BY
        CName
    ) foo
    JOIN
    MyTable M ON foo.CName = M.CName AND foo.First = M.Inserted
Run Code Online (Sandbox Code Playgroud)

  • @nuit9:当然它不适用于位和 10 列。这些事实都不是你的问题。您可以使用第二种技术或 Ben Thul 的技术。我具体回答了您的问题,并指出了如何更普遍地解决问题。 (3认同)

Ben*_*hul 20

在SQL 2k5 +中,您可以执行以下操作:

;with cte as (
  select CName, AddressLine,
  rank() over (partition by CName order by AddressLine) as [r]
  from MyTable
)
select CName, AddressLine
from cte
where [r] = 1
Run Code Online (Sandbox Code Playgroud)

  • 请说明等级,分区和[r]的作用 (2认同)

Fra*_*ank 10

您可以使用row_number()获取行的行号.它使用over命令 - 该partition by子句指定何时重新开始编号,并order by选择要对行号进行排序的内容.即使您order by在查询的末尾添加了一个,它也会over在编号时保留命令中的顺序.

select *
from mytable
where row_number() over(partition by Name order by AddressLine) = 1
Run Code Online (Sandbox Code Playgroud)

  • 在postgresql中,WHERE子句中不允许使用窗口函数 (6认同)
  • “ROW_NUMBER()”在 Teradata 的“Where”子句中也不起作用 (4认同)
  • MS-SQL均不允许这样做。 (2认同)

Fat*_*ici 5

您可以使用如下row_numer() over(partition by ...)语法:

select * from
(
select *
, ROW_NUMBER() OVER(PARTITION BY CName ORDER BY AddressLine) AS row
from myTable
) as a
where row = 1
Run Code Online (Sandbox Code Playgroud)

它的作用是创建一个名为的列row,该列是一个计数器,每次看到该列时都会递增CName,并用索引这些出现AddressLine。通过征收where row = 1,可以选择CNameAddressLine来首字母顺序排列。如果order bydesc的话,那就挑CNameAddressLine是最后的字母顺序。

  • 这样做的另一个好处是不限制您只能看到第一行。就我而言,我实际上是在寻找前 3 次出现作为感官检查的手段。最后一行就是“where row < 4” (3认同)