SQL查询过滤器根据其他2列中的值定位列中的DUPLICATES

时间:2015-06-10 05:12:13

标签: sql-server filter duplicates

我正在使用SQL Server 2014,我正在使用名为ReservationStay的表。它包含所有客人的姓名,抵达日期和出发日期的记录。已经开展了一项操作,将数百名客人的记录分成2个单独的条目,这意味着这些条目现在具有相同的客人姓名,但具有不同的到达日期和出发日期。

原始条目的示例:

 Name         ArrivalDate        DepartureDate
Simon G       2015-06-01          2015-06-08

以下是拆分操作在2015-06-03之后发生的事情:

 Name         ArrivalDate        DepartureDate
Simon G       2015-06-01          2015-06-03
Simon G       2015-06-03          2015-06-08

这项拆分行动在几天内进行。

我的查询中需要一个过滤器,它会考虑以下因素:

WHERE Name是重复的,第一个条目的DepartureDate =第二个条目的ArrivalDate。

基本上,我想重新构建原始条目。

如何编写此过滤器?

3 个答案:

答案 0 :(得分:0)

可以使用简单的INNER JOIN("自我加入")来完成:

SELECT a.Name, a.ArrivalDate, b.DepartureDate
FROM dtab a 
INNER JOIN dtab b ON b.Name=a.Name
AND b.ArrivalDate=a.DepartureDate

http://sqlfiddle.com/#!9/51ea3/2

我在表格中添加了几行,以便有一个符合条件的示例:

CREATE TABLE dtab (Name varchar(11),ArrivalDate varchar(10),DepartureDate varchar(10));
INSERT INTO dtab (Name,ArrivalDate,DepartureDate)
VALUES
('Simon G', '2015-06-01', '2015-06-03'),
('Simon G', '2015-06-03', '2015-06-08'),
('Peter M', '2015-03-07', '2015-03-15'),
('Peter M', '2015-05-05', '2015-05-10');

并获得所需的结果

|    Name | ArrivalDate | DepartureDate |
|---------|-------------|---------------|
| Simon G |  2015-06-01 |    2015-06-08 |

修改

注意,为了重建未拆分表,您还需要列出之前已拆分 的条目。为此,您可以执行以下操作:

WITH combined AS (
 SELECT a.Name cnam, a.ArrivalDate carr, b.DepartureDate cdep
 FROM dtab a 
 INNER JOIN dtab b ON b.Name=a.Name
 AND b.ArrivalDate=a.DepartureDate
)
SELECT d.* FROM dtab d
LEFT JOIN combined ON cnam=Name AND (carr=ArrivalDate OR cdep=DepartureDate)
WHERE cdep IS NULL
UNION ALL 
SELECT * FROM combined

我将原始的SELECT语句放入公用表格表达式(combined)中,并用它来检查原始表格中任何条目的到达或出发日期是否一致。如果是这样,原始条目将列出,否则它们将在UNION中列出combined表的条目。

现在我们得到

|    Name | ArrivalDate | DepartureDate |
|---------|-------------|---------------|
| Peter M |  2015-03-07 |    2015-03-15 |
| Peter M |  2015-05-05 |    2015-05-10 |
| Simon G |  2015-06-01 |    2015-06-08 |

http://sqlfiddle.com/#!6/7d325/5

此解决方案将在SQL Server 2005中起作用(SQL Server 2012中引入了LAG / LEAP)。

答案 1 :(得分:0)

    declare @t table (name varchar(10),Arrivaldate varchar(20),Departure varchar(20)) 
    insert into @t(name,Arrivaldate,Departure)
values 
('Simon G','2015-06-01','2015-06-03'),
('Simon G','2015-06-03','2015-06-08')

    Select A.name,A.Arrivaldate,A.Departure from (
    select NAME,MIN(Arrivaldate)Arrivaldate,MAX(Departure)Departure from @t GROUP BY NAME)A

答案 2 :(得分:0)

您可以使用LEADLAG窗口函数来查找已拆分的记录:

SELECT Name, MIN(ArrivalDate) AS ArrivalDate, MAX(DepartureDate) AS DepartureDate
FROM (
SELECT Name, ArrivalDate, DepartureDate, 
       CASE 
          WHEN ArrivalDate = LAG(DepartureDate) OVER (PARTITION BY Name 
                                                      ORDER BY ArrivalDate) 
               OR                                                     

               DepartureDate = LEAD(ArrivalDate) OVER (PARTITION BY Name 
                                                       ORDER BY ArrivalDate)
          THEN 1
          ELSE 0
       END AS HasBeenSplit                                                       
FROM mytable ) t
GROUP BY Name, HasBeenSplit

此查询将为您提供表格的原始版本。

Demo here