SQLite从具有相同主键的多行表中删除重复项

时间:2019-06-23 13:35:28

标签: sql sqlite

我的问题是按照导演的电影数量降序列出所有导演10部或以上电影的导演。返回导演的姓名和导演的电影数量

我有两个表,一个是Director表,它具有ID(主键),MID,PID列。另一个是具有PID(主键),名称,性别列的人员表。

以下是我的查询

SELECT Name, COUNT(*) movies_directed
FROM Director
LEFT JOIN Person USING(PID)
GROUP BY PID
HAVING movies_directed >= 10
ORDER BY movies_directed DESC;

但是这里的问题是,在Person中有多个具有相同PID的行。

这是示例数据

当我执行查询时

SELECT * FROM Person WHERE Name LIKE '%Andy Serkis%';

结果是

index        PID          Name           Gender
4        'nm0785227'     **' Andy Serkis'**  'Male'
36821    'nm0785227'     'Andy Serkis'   'Male'

第一行中的名称有一个额外的空间。这些重复项需要删除

3 个答案:

答案 0 :(得分:0)

  

但是这里的问题是在Person中有多个具有相同PID的行。

这真的没有道理。大概PIDPerson表的主键。这意味着Person中每个值只有一行。 Director中可能有多行-因为一个人可以导演多部电影。

我认为您的查询将返回正确的结果。但是,它的措词不正确。

使用内部联接会更好,因为您只考虑导演了至少一部电影的人(实际上,至少有十部电影)。所以:

SELECT p.Name, COUNT(*) as movies_directed
FROM Person p JOIN
     Director d
     USING (PID)
GROUP BY PID, p.Name
HAVING movies_directed >= 10
ORDER BY movies_directed DESC;

注意:

  • 当您引用多个表时,应限定所有列名。一个例外是USING子句中的列。
  • 表别名使查询更易于编写和阅读。
  • 在您的版本中,您有COUNT(*)。对于LEFT JOIN,这通常是不合适的。通常,您需要在 second 表中计算匹配项。

答案 1 :(得分:0)

这应该可以解决问题。

SELECT Name, COUNT(*) movies_directed
FROM Director
Where exists
(SELECT 1 FROM  Person 
WHERE Director.PID = Person.PID)
GROUP BY PID
HAVING movies_directed >= 10
ORDER BY movies_directed DESC;

但是理想情况下,您想要引用具有唯一人员ID的单独表并使用join子句。

答案 2 :(得分:0)

首先执行以下DELETE语句:

delete from Person 
where exists (
  select 1 from Person p 
  where p.pid = Person.pid and p.name <> Person.name and p.rowid < Person.rowid
);

此操作将删除重复的PID,仅保留较低RowId的那个。
然后执行以下UPDATE语句:

update Person
set name = trim(name);

修复任何在结尾或开头包含空格的名称。
如果还有其他不一致之处,您也可以执行类似的UPDATE语句。
然后,如果您对表使用适当的别名并用它们限定列,那么您的代码应该可以工作。