如何在SQL Server中按多列分组

时间:2016-07-21 05:23:18

标签: sql-server group-by

我理解GROUP BY是如何工作的,我也理解为什么我的查询没有带来我期待的结果。但是,在这种情况下消除重复的最佳方法是什么?

假设我们有以下表格:

城市

Id    Name
---------------------
1     Seattle
2     Los Angeles
3     San Francisco

Id    Name            CityId
----------------------------
1     John Smith      1
2     Peter Taylor    1
3     Kate Elliot     1
4     Bruno Davis     2
5     Jack Brown      2
6     Bob Stewart     2
7     Tom Walker      3
8     Andrew Garcia   3
9     Kate Bauer      3

我想检索所有城市的列表,以及每个城市中只有一个的人。

使用GROUP BY

SELECT c.Id, c.Name as PersonName, p.Name as CityName
FROM City c
INNER JOIN Person p ON p.CityId = c.Id
GROUP BY c.Name, p.Name

结果:

Id    PersonName      CityName
----------------------------
1     John Smith      Seattle
1     Peter Taylor    Seattle
1     Kate Elliot     Seattle
2     Bruno Davis     Los Angeles
2     Jack Brown      Los Angeles
2     Bob Stewart     Los Angeles
3     Tom Walker      San Francisco
3     Andrew Garcia   San Francisco
3     Kate Bauer      San Francisco

使用DISTINCT

SELECT DISTINCT c.Id, c.Name as PersonName, p.Name as CityName
FROM City c
INNER JOIN Person p ON p.CityId = c.Id

结果相同。

只是要非常清楚。这是预期的结果:

Id    PersonName      CityName
----------------------------
1     John Smith      Seattle
2     Bruno Davis     Los Angeles
3     Tom Walker      San Francisco

subquery会成为此案的唯一解决方案吗?

3 个答案:

答案 0 :(得分:1)

这是一个解决方案,它使用子查询来识别"第一个匹配"来自Person表,我将其解释为每个城市组中id值最低的人。

SELECT t1.Id,
       t1.Name AS PersonName,
       t2.Name AS CityName
FROM Person t1
INNER JOIN City t2
    ON t1.CityId = t2.Id
INNER JOIN
(
    SELECT CityId, MIN(Id) AS minId
    FROM Person
    GROUP BY CityId
) t3
    ON t1.CityId = t3.CityId AND t1.Id = t3.minID

使用窗口函数可能还有一种方法可以做到这一点。

答案 1 :(得分:1)

PartitionCitySub-Query可以解决问题:

SELECT R.ID, R.PERSON_NAME, R.CITY_NAME FROM
(
    SELECT P.ID, P.NAME [PERSON_NAME], C.NAME [CITY_NAME],
             ROW_NUMBER() OVER (PARTITION BY C.ID ORDER BY P.ID) AS rn
    FROM Person P
    INNER JOIN CITY C
    ON P.CITYID = C.ID
) R
WHERE R.rn = 1

结果:

1       John Smith      Seattle
4       Bruno Davis     Los Angeles
7       Tom Walker      San Francisco

答案 2 :(得分:-1)

如果上述不起作用,请尝试不同

SELECT tbl.Id,
       tbl.PersonName,
       tbl.CityName
FROM
(
   SELECT c.Id, c.Name as PersonName, p.Name as CityName
   FROM City c
   INNER JOIN Person p ON p.CityId = c.Id
   ORDER BY c.Name, p.Name
) AS tbl
GROUP BY tbl.PersonName

编辑

这是查询,

   SELECT DISTINCT c.Id, c.Name as PersonName, p.Name as CityName
   FROM City c
   INNER JOIN Person p ON p.CityId = c.Id
   ORDER BY c.Name, p.Name