如何根据位置 ID 和名称从 table 中删除重复项
How can I delete duplicates from a table based on a location id and name
列是:姓名,Location_Name,Location_ID
我想检查名称和 Location_ID,如果有两个相同,我想 delete/remove 那一行。
例如:如果名称 John Fox 在位置 ID 4 出现了两次或更多次,我只想保留一个。
之后,我想统计每个地点有多少人。
Location_Name1:45
Location_Name2:66
ETC...
位置名称和位置 Id 是相关的。
Sample data
Code I tried
删除重复项是一种常见的模式。您将序列号应用于所有重复项,然后删除任何不是第一个的。在这种情况下,我可以任意排序,但您可以选择保留 PK 值最低的那个或最后修改的那个或其他任何东西 - 只需更新 ORDER BY
以对您要保留的那个进行排序。
;WITH cte AS
(
SELECT *, rn = ROW_NUMBER() OVER
(PARTITION BY Name, Location_ID ORDER BY @@SPID)
FROM dbo.TableName
)
DELETE cte WHERE rn > 1;
然后计算,假设给定的 Location_Name
不能有两个不同的 Location_ID
(这就是模式 + 示例数据如此有用的原因):
SELECT Location_Name, People = COUNT(Name)
FROM dbo.TableName
GROUP BY Location_Name;
如果 Location_Name
和 Location_ID
不是 紧密耦合(例如,可能 Location_ID = 4, Location_Name = Place 1
和 Location_ID = 4, Location_Name = Place 2
那么你如果您按 Location_ID
分组,或者承认其中一列可能毫无意义,您将不得不定义如何确定要显示的位置。
如果Location_Name
和Location_ID
紧耦合,它们不应该都存储在这个table。你应该有一个 lookup/dimension table 来存储这两列(一次!)并且你使用最小的数据类型作为你在事实 table 中记录的键(它重复一遍又一遍)。这有几个好处:
- 扫描较大的table速度更快,因为它没有那么宽
- 存储空间减少了,因为您不再一遍又一遍地重复长字符串
- 聚合更清晰,可以在聚合后加入取名,速度会更快
- 如果您需要更改地点的名称,您只需更改一处即可
示例代码
CREATE TABLE People_Location
(
Name VARCHAR(30) NOT NULL,
Location_Name VARCHAR(30) NOT NULL,
Location_ID INT NOT NULL,
)
INSERT INTO People_Location
VALUES
('John Fox', 'Moon', 4),
('John Bear', 'Moon', 4),
('Peter', 'Saturn', 5),
('John Fox', 'Moon', 4),
('Micheal', 'Sun', 1),
('Jackie', 'Sun', 1),
('Tito', 'Sun', 1),
('Peter', 'Saturn', 5)
获取位置和计数
select Location_Name, count(1)
from
(select Name, Location_Name,
rn = ROW_NUMBER() OVER (PARTITION BY Name, Location_ID ORDER BY Name)
from People_Location
) t
where rn = 1
group by Location_Name
结果
Moon 2
Saturn 1
Sun 3
列是:姓名,Location_Name,Location_ID
我想检查名称和 Location_ID,如果有两个相同,我想 delete/remove 那一行。
例如:如果名称 John Fox 在位置 ID 4 出现了两次或更多次,我只想保留一个。
之后,我想统计每个地点有多少人。 Location_Name1:45 Location_Name2:66 ETC... 位置名称和位置 Id 是相关的。 Sample data
Code I tried
删除重复项是一种常见的模式。您将序列号应用于所有重复项,然后删除任何不是第一个的。在这种情况下,我可以任意排序,但您可以选择保留 PK 值最低的那个或最后修改的那个或其他任何东西 - 只需更新 ORDER BY
以对您要保留的那个进行排序。
;WITH cte AS
(
SELECT *, rn = ROW_NUMBER() OVER
(PARTITION BY Name, Location_ID ORDER BY @@SPID)
FROM dbo.TableName
)
DELETE cte WHERE rn > 1;
然后计算,假设给定的 Location_Name
不能有两个不同的 Location_ID
(这就是模式 + 示例数据如此有用的原因):
SELECT Location_Name, People = COUNT(Name)
FROM dbo.TableName
GROUP BY Location_Name;
如果 Location_Name
和 Location_ID
不是 紧密耦合(例如,可能 Location_ID = 4, Location_Name = Place 1
和 Location_ID = 4, Location_Name = Place 2
那么你如果您按 Location_ID
分组,或者承认其中一列可能毫无意义,您将不得不定义如何确定要显示的位置。
如果Location_Name
和Location_ID
紧耦合,它们不应该都存储在这个table。你应该有一个 lookup/dimension table 来存储这两列(一次!)并且你使用最小的数据类型作为你在事实 table 中记录的键(它重复一遍又一遍)。这有几个好处:
- 扫描较大的table速度更快,因为它没有那么宽
- 存储空间减少了,因为您不再一遍又一遍地重复长字符串
- 聚合更清晰,可以在聚合后加入取名,速度会更快
- 如果您需要更改地点的名称,您只需更改一处即可
示例代码
CREATE TABLE People_Location
(
Name VARCHAR(30) NOT NULL,
Location_Name VARCHAR(30) NOT NULL,
Location_ID INT NOT NULL,
)
INSERT INTO People_Location
VALUES
('John Fox', 'Moon', 4),
('John Bear', 'Moon', 4),
('Peter', 'Saturn', 5),
('John Fox', 'Moon', 4),
('Micheal', 'Sun', 1),
('Jackie', 'Sun', 1),
('Tito', 'Sun', 1),
('Peter', 'Saturn', 5)
获取位置和计数
select Location_Name, count(1)
from
(select Name, Location_Name,
rn = ROW_NUMBER() OVER (PARTITION BY Name, Location_ID ORDER BY Name)
from People_Location
) t
where rn = 1
group by Location_Name
结果
Moon 2
Saturn 1
Sun 3