SQL最简单的方法来过滤掉相同的行?

时间:2013-05-28 19:40:54

标签: sql

SQL noob here - 我想在一个月内进行比较,有多少人改姓。我的技能限制了我,所以我能想到的最简单的方法是运行2个查询:

Query 1:
SELECT firstname, lastname
FROM names_dataset
WHERE date='2013-05-27' 

Query 2:
SELECT firstname, lastname
FROM names_dataset
WHERE date='2013-04-27'

Result query 1:
John        Smith
Michael     Johnson
James       Williams

Result query 2:
John        Smith
Michael     Johnson
James       Brown

我想要的唯一结果是“詹姆斯布朗”,它在不同的日期改变了col2。

我从两个查询(没有更改名称的ppl)中得到了很多重复的结果,我怎么只过滤掉col2变化的行?

4 个答案:

答案 0 :(得分:1)

    SELECT t1.firstname,
           t1.lastname AS from_lastname,
           t2.lastname AS to_lastname
      FROM names_dataset AS t1
INNER JOIN names_dataset as t2
        ON t1.firstname = t2.firstname
     WHERE t1.date='2013-04-27' 
       AND t2.date='2013-05-27' 
       AND t1.lastname <> t2.lastname

这将提供在两个日期具有相同名字但姓氏不同的行的列表。

答案 1 :(得分:1)

鉴于您的名字字段是唯一的,这有效:

SELECT *
FROM (SELECT firstname, lastname
        FROM names_dataset
        WHERE date='2013-05-27'
     )day1
JOIN
     (SELECT firstname, lastname
        FROM names_dataset
        WHERE date='2013-04-27')
     )day2
ON day1.firstname = day2.firstname
WHERE day1.lastname <> day2.lastname

这会返回所有内容,如果您只想要'James Brown',那么您可以将选择部分更改为:

SELECT day2.firstname, day2.lastname

答案 2 :(得分:0)

也许您会发现这种方法很有帮助。我使用它为一组中出现的每一行分配“已添加”或“已删除”,而不是另一组:

select firstname, lastname,
       (case when MAX(which) = 'later' then 'ADDED'
             when MAX(which = 'earlier' then 'REMOVED'
             else '???'
        end)
from ((SELECT firstname, lastname, 'later' as which
       FROM names_dataset
       WHERE date='2013-05-27' 
      ) union all
      (select firstname, lastname, 'earlier'
       FROM names_dataset
       WHERE date='2013-04-27' 
      )
     ) t
group by firstname, lastname
having count(*) = 1;

它结合了两组中的名称并计算出现一次的数字。如果事件发生在较晚的时间段,则添加记录。如果仅在较早的时间段内,则将其删除。

此外,这是标准SQL,因此它应该适用于大多数数据库。

答案 3 :(得分:0)

SQL Fiddle demo

我为此使用了SQL Server;我会通过自我内部联接来处理这个问题(注意ID字段仅用于测试目的)。通过名字将表连接到自身,并查找名字和姓氏字段不匹配的位置。如果您怀疑名字可能已更改,请将此查询反转为名字。

最终查询:

SELECT *
FROM names n1
  INNER JOIN names n2 ON n1.FirstName = n2.FirstName
WHERE n1.LastName <> n2.LastName

或者,my preferred method (SQL Fiddle also)将使用ID字段并加入ID字段。这将记录名字或姓氏的任何变化,并且整体上更加简单,加上它解决了第一条评论,正确地指出了一个问题 - 你怎么知道詹姆斯不是一个新人?这个查询:

SELECT *
FROM names n1
  INNER JOIN names n2 ON n1.ID = n2.ID
WHERE n1.FirstName <> n2.FirstName
  OR n1.LastName <> n2.LastName