我理解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
会成为此案的唯一解决方案吗?
答案 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)
Partition
按City
和Sub-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