SQL 查询过滤器以根据其他 2 列中的值在一列中查找重复项

SQL Query Filter to locate DUPLICATES in a column based on Values in 2 other columns

我正在使用 SQL Server 2014,并且正在使用名为 ReservationStay 的 table。它包含所有客人的姓名、到达日期和离开日期的记录。已进行一项操作,将数百位客人的记录拆分为 2 个单独的条目,这意味着这些条目现在具有相同的客人姓名,但到达日期和离开日期不同。

原始条目示例:

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

下面是拆分操作生效后发生的事情,比如说,2015 年 6 月 3 日:

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

这个拆分操作进行了好几天

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

WHERE 名称重复,第一个条目的出发日期 = 第二个条目的到达日期。

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

如何编写此过滤器?

可以用一个简单的 INNER JOIN ("self-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

我在 table 中添加了几行,以提供一个 满足条件的示例:

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 |

编辑

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

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语句放到一个普通的table表达式中(combined),然后用它来检查原来的table是否到达或离开日期这些条目中的任何一个都是一致的。如果他们这样做,原始条目将 列出,否则它们将与 combined table 的条目一起列在 UNION 中。 =23=]

现在我们得到

|    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(LAG / LEAP 在 SQL Server 2012 中引入)。

    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

您可以使用 LEADLAG window 函数来定位已拆分的记录:

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

此查询将为您返回 table 的原始版本。

Demo here