2

好吧,也许没有 SQL 语句可以帮助我解决这个问题,所以我不知道该叫什么。

在我正在处理的 Access 2013 数据库中:

所有表都有字段name address phone city state zip

什么用作primary key is the phone number,但未设置为 Access 中的主键。

我想从此数据库中删除重复记录。

电话号码是这里明显的唯一标识符,但我如何能够检索所有数据,按电话号码对其进行排序,并删除任何具有电话号码但保留其中一个的记录?

在大多数情况下,我相当确定地址、姓名和所有其他字段都会匹配,我只想清理表格,以免重复。

4

2 回答 2

1

我假设这phone是你的伪主键。意思是:它应该使用查询变得唯一。

对于 Postgres,以下将起作用:

SELECT DISTINCT ON (phone)
  *
FROM your_table

它为每个电话号码选择任意一行,从而使电话号码保持不同。

也许有一个等价DISTINCT ON (...)于访问?


如果您id在表中有一个 REAL UNIQUE 标识符,这将起作用:

SELECT *
FROM your_table
WHERE id IN (
  SELECT min(id)
  FROM your_table
  GROUP BY phone
)

得到它的工作,也许不完美(最快的查询),但它正在工作!

SELECT *
FROM (
  SELECT ROW_NUMBER() OVER () AS pseudoid, *
  FROM your_table
) x
JOIN (
  SELECT MIN(pseudoid) AS pseudoid
  FROM (
    SELECT ROW_NUMBER() OVER () AS pseudoid, phone
    FROM your_table
  ) z
  GROUP BY z.phone
) y
ON x.pseudoid = y.pseudoid

解释:

首先(第 9-10 行):

SELECT ROW_NUMBER() OVER () AS pseudoid, phone
FROM your_table

这会为每一行(加上电话号码)提供一个 pseudo_id。所以我们有重复的条目,但每个条目都有其唯一的伪标识。然后(第 7-12 行):

SELECT MIN(pseudoid) AS pseudoid
FROM (
  SELECT ROW_NUMBER() OVER () AS pseudoid, phone
  FROM your_table
) z
GROUP BY z.phone

这使我们的电话号码独一无二,并始终选择 MIN(伪)。然后(第 3-4 行):

SELECT ROW_NUMBER() OVER () AS pseudoid, *
FROM your_table

为整个表创建一个伪标识。

然后我们加入这些表:这为每个电话号码提供了具有最小伪 ID 的完整行(+伪 ID)。

小一点(也许更快):

WITH pseudo_id_table AS (SELECT ROW_NUMBER() OVER () AS pseudoid, * FROM your_table)
SELECT *
FROM pseudo_id_table x
JOIN (
  SELECT MIN(pseudoid) AS pseudoid
  FROM pseudo_id_table
  GROUP BY phone
) y
ON x.pseudoid = y.pseudoid
于 2013-02-28T23:17:39.833 回答
0

有一个更简单的方法:

  1. 复制表(仅结构)
  2. 将手机设为主键
  3. 将旧表中的数据附加到新表中。任何重复的记录都将在追加时拒绝。
  4. 删除旧表
  5. 将新表重命名为旧表名

这仅在您保留的记录确实无关紧要时才有效。

于 2013-03-01T12:02:18.820 回答