SQL如何选择所有重复id的行,但不是每行的第一行?
Posted
技术标签:
【中文标题】SQL如何选择所有重复id的行,但不是每行的第一行?【英文标题】:SQL How to SELECT all rows with repeated id's but not the first of each one? 【发布时间】:2018-05-23 03:02:27 【问题描述】:我有一个 ID 重复的数据库,我想更改这个重复 ID 的名称。
所以,我有一个车辆数据库,在列中我有许可证号 (id)、车辆类型、颜色和品牌。
所有的 id 在数据库中都是重复的,我想选择除每个不同 ID 的第一行之外的所有 ID(类似于“DISTINCT id”但相反......)。
编辑 2:
我已经创建了这个表
DROP TABLE IF EXISTS Proces1 CASCADE;
CREATE TABLE Proces1 AS
(
SELECT id_importat AS id_aux, driver_city AS city_aux, driver_state AS state_aux, gender AS g_aux, race AS r_aux
FROM ImportaViolations
WHERE id_importat IN (
SELECT id_importat
FROM ImportaViolations
GROUP BY id_importat
HAVING (COUNT(*) > 1))
GROUP BY id_importat, driver_city, driver_state, gender, race
);
在这张表中,我重复了 id,但列中的信息不同。
类似:
id_aux city_aux state_aux g_aux r_aux
1 London England M WHITE
1 London England F BLACK
2 Madrid Spain M BLACK
2 London England F WHITE
2 London England M WHITE
...
所以现在,我想选择所有具有重复 id_aux 的行,除了每个不同 id_aux 的第一个。所以我想得到这个最终结果(在这个例子中):
id_aux city_aux state_aux g_aux r_aux
1 London England F BLACK
2 London England F WHITE
2 London England M WHITE
...
【问题讨论】:
我删除了不兼容的数据库标签。请仅使用您真正使用的数据库进行标记。 您可能需要添加更具体的示例数据。例如,您可以只说WHERE Column1 <> 'a'
并获得您想要的结果。我想你的实际数据更复杂。同样假设它更复杂,您将需要一种方法来知道哪一行是“第一”行。
我真的不明白这个问题。 select * from table where column1 in ('c','e')?
SQL 数据存储在无序集中,这意味着仅仅因为一行出现在您的结果集中,您需要一个ORDER BY
来保证它是“第一”行。
您可以使用限制和偏移量.. 示例.. $sql = "SELECT * FROM tables LIMIT 10 OFFSET 15";上面的 SQL 查询说“只返回 10 条记录,从第 16 条记录开始(偏移量 15)”:您也可以使用 DISTINCT 去除重复的 ID
【参考方案1】:
我只是修改了这个问题的答案,以更好地满足您的需求: Select first row in each GROUP BY group?
基本上,我没有使用rk = 1
选择每个组的第一个,而是将其更改为rk > 1
并切换列名以匹配您的。
WITH MyTable AS (
SELECT p.Id,
p.Column1,
p.Column2,
ROW_NUMBER() OVER(PARTITION BY p.Column1
ORDER BY p.Column2 DESC) AS rk
FROM MyTable p)
SELECT s.*
FROM MyTable t
WHERE s.rk > 1
编辑:将 rk = 2
更改为 rk > 1
以选择除第一个以外的所有内容,而不仅仅是第二个。
【讨论】:
如果它按我的意愿工作,我会立即尝试,但我认为它会!谢谢;) 如果我有 5 个不同的列怎么办?如何创建 ROW_NUMBER 函数?对不起我的水平,我刚开始使用sql :) 你没有创建它。它只是存在。【参考方案2】:这样的?
SELECT
ID
, Column1
, Column2
FROM
(
SELECT
ID
, Column1
, Column2
, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Column1, Column2) R
FROM YourTable
) Q
WHERE R > 1
编辑 2 的更新:
SELECT
id_aux
, city_aux
, state_aux
, g_aux
, r_aux
FROM
(
SELECT
id_aux
, city_aux
, state_aux
, g_aux
, r_aux
, ROW_NUMBER() OVER (PARTITION BY id_aux ORDER BY id_aux) R
FROM YourTable
) Q
WHERE R > 1
【讨论】:
谢谢,但我已经尝试过了,但它并没有达到我的预期...... :( 在什么意义上?我也许可以做出调整。 嗨,克里斯,我在问题中添加了新信息,以帮助您理解我(编辑 2)。谢谢。 嗨 Andres - 我明白,但根据 Aaron Dietz 的评论,您需要某种ORDER BY
来确定每个 ID 的第一条记录 - 除非没关系?跨度>
没关系,我只想从一个重复的 id 中获取所有这些(在每个重复的 id 中),它不需要是第一个 :) 但只是一个【参考方案3】:
请密切注意以下演示中的行顺序。 & 请注意,我还添加了一些额外的行。最初,我们从 ImportaViolations
中创建的“随机”行开始,对于这个示例,每个 id_importat 的“第一行”
INSERT INTO ImportaViolations
(id_importat, driver_city, driver_state, gender, race)
VALUES
(1, 'London', 'England', 'M', 'WHITE'),
(2, 'Madrid', 'Spain', 'M', 'BLACK'),
但是如果我们运行this query(没有“order by”):
SELECT id_importat AS id_aux, driver_city AS city_aux
, driver_state AS state_aux, gender AS g_aux, race AS r_aux
, rn
FROM (
select id_importat, driver_city, driver_state, gender, race
, row_number() over(partition by id_importat) as rn
from ImportaViolations
) d
WHERE rn = 1
这是结果:
| id_aux | city_aux | state_aux | g_aux | r_aux | rn |
|--------|----------|-----------|-------|-------|----|
| 1 | London | England | M | WHITE | 1 |
| 2 | London | England | F | WHITE | 1 |
该结果受到必要的partition by
的影响(如果没有这个,表格中总共会有一行行号为 1)。
所以: 这个故事的寓意是,您必须仔细考虑 ORDER 以确定每个 id_importat 的“第一行”应该是什么。
SQL Fiddle Demo
CREATE TABLE ImportaViolations
(id_importat int, driver_city varchar(6), driver_state varchar(7), gender varchar(1), race varchar(5))
;
INSERT INTO ImportaViolations
(id_importat, driver_city, driver_state, gender, race)
VALUES
(1, 'London', 'England', 'M', 'WHITE'),
(2, 'Madrid', 'Spain', 'M', 'BLACK'),
(1, 'London', 'England', 'F', 'BLACK'),
(2, 'London', 'England', 'M', 'WHITE'),
(1, 'London', 'England', 'F', 'BLACK'),
(2, 'Madrid', 'Spain', 'M', 'BLACK'),
(2, 'London', 'England', 'F', 'WHITE'),
(1, 'London', 'England', 'M', 'WHITE'),
(2, 'London', 'England', 'F', 'WHITE')
;
主查询:
DROP TABLE IF EXISTS Proces1 CASCADE;
CREATE TABLE Proces1 AS
(
SELECT id_importat AS id_aux, driver_city AS city_aux
, driver_state AS state_aux, gender AS g_aux, race AS r_aux
, rn
FROM (
select id_importat, driver_city, driver_state, gender, race
, row_number() over(partition by id_importat order by 1) as rn
from ImportaViolations
) d
WHERE rn > 1
);
查询 1:
select * from Proces1
Results:
| id_aux | city_aux | state_aux | g_aux | r_aux | rn |
|--------|----------|-----------|-------|-------|----|
| 1 | London | England | F | BLACK | 2 |
| 1 | London | England | F | BLACK | 3 |
| 1 | London | England | M | WHITE | 4 |
| 2 | Madrid | Spain | M | BLACK | 2 |
| 2 | Madrid | Spain | M | BLACK | 3 |
| 2 | London | England | F | WHITE | 4 |
| 2 | London | England | M | WHITE | 5 |
查询 2:
select * from ImportaViolations
Results:
| id_importat | driver_city | driver_state | gender | race |
|-------------|-------------|--------------|--------|-------|
| 1 | London | England | M | WHITE |
| 2 | Madrid | Spain | M | BLACK |
| 1 | London | England | F | BLACK |
| 2 | London | England | M | WHITE |
| 1 | London | England | F | BLACK |
| 2 | Madrid | Spain | M | BLACK |
| 2 | London | England | F | WHITE |
| 1 | London | England | M | WHITE |
| 2 | London | England | F | WHITE |
【讨论】:
好的。谢谢。请注意,在决定什么是“第一行”时,“顺序”至关重要,使用row_number() over()
即使没有指定“顺序依据”也会因为分区而影响顺序。以上是关于SQL如何选择所有重复id的行,但不是每行的第一行?的主要内容,如果未能解决你的问题,请参考以下文章