0

我正在使用 OVER 和 Partition by 来获取数据集的 mindate 和 max date。

|ResdetId | bookingdate | Amount | AmountExcl |
-----------------------------------------------
|120106   | 2018-02-04  |  75.00 |  70.7547   |
|120106   | 2018-02-05  |  75.00 |  70.7547   |
|120106   | 2018-02-06  |  90.00 |  84.9057   |
|120106   | 2018-02-08  |  75.00 |  70.7547   |
|120106   | 2018-02-09  |  75.00 |  70.7547   |

我正在使用这个查询

select distinct ResDetId, Amount, AmountExcl, 
    min(Bookingdate) OVER(Partition by ResDetId, Amount, AmountExcl) as Mindate,
    max(Bookingdate) OVER(Partition by ResDetId, Amount, AmountExcl) as MaxDate
 from @Cumulatedbookingdetails

我得到了这个结果

|ResdetId | Amount | AmountExcl | MinDate    | MaxDate     |
------------------------------------------------------------
|120106   | 75.00  |  70.7547   | 2018-02-04 |  2018-02-09 |
|120106   | 90.00  |  84.9057   | 2018-02-06 |  2018-02-06 |

正如我们所见,数据集中缺少日期 2018-02-07 记录。所以,我需要这样的结果

|ResdetId | Amount | AmountExcl | MinDate    | MaxDate     |
------------------------------------------------------------
|120106   | 75.00  |  70.7547   | 2018-02-04 |  2018-02-05 |
|120106   | 75.00  |  70.7547   | 2018-02-08 |  2018-02-09 |
|120106   | 90.00  |  84.9057   | 2018-02-06 |  2018-02-06 |
4

4 回答 4

1

解决诸如此类的“岛屿和差距”问题的一种方法是使用递归 CTE 来构建岛屿。我们让非递归部分(在 上方union)找到标记每个岛开始的行,递归部分一次增长每个岛一个匹配项。

不幸的是,CTE 的最终结果包含用于构建岛的所有中间行,因此您需要一个 final GROUPby 来选择最终的岛:

declare @t table (ResdetId int, bookingdate date, Amount decimal(9,3), AmountExcl decimal (9,3))
insert into @t(ResdetId,bookingdate,Amount,AmountExcl) values
(120106,'20180204',75.00,70.7547),
(120106,'20180205',75.00,70.7547),
(120106,'20180206',90.00,84.9057),
(120106,'20180208',75.00,70.7547),
(120106,'20180209',75.00,70.7547)

;With Islands as (
    select ResdetId, Amount, AmountExcl,bookingdate as MinDate,bookingDate as MaxDate
    from @t t
    where not exists (select * from @t t2
        where t2.ResdetId = t.ResdetId
        and t2.Amount = t.Amount
        and t2.AmountExcl = t.AmountExcl
        and t2.bookingdate = DATEADD(day,-1,t.BookingDate))
    union all
    select i.ResdetId, i.Amount,i.AmountExcl,i.MinDate,t.bookingDate
    from Islands i
        inner join
        @t t
        on t.ResdetId = i.ResdetId
        and t.Amount = i.Amount
        and t.AmountExcl = i.AmountExcl
        and t.bookingdate = DATEADD(day,1,i.MaxDate)
)
select
    ResdetId, Amount, AmountExcl,MinDate,MAX(MaxDate) as MaxDate
from
    Islands
group by ResdetId, Amount, AmountExcl,MinDate

结果:

ResdetId    Amount    AmountExcl   MinDate    MaxDate
----------- --------- ------------ ---------- ----------
120106      75.000    70.755       2018-02-04 2018-02-05
120106      75.000    70.755       2018-02-08 2018-02-09
120106      90.000    84.906       2018-02-06 2018-02-06
于 2018-08-28T09:01:35.987 回答
0

这会更容易做到GROUP BYOVER并且DISTINCT是执行相同查询的“更难”的方法:

WITH VTE AS(
    SELECT ResdetId,
           CONVERT(date,bookingdate) AS bookingdate,
           Amount,
           AmountExcl
    FROM (VALUES (120106,'20180204',75.00,70.7547),
                 (120106,'20180205',75.00,70.7547),
                 (120106,'20180206',90.00,84.9057),
                 (120106,'20180208',75.00,70.7547),
                 (120106,'20180209',75.00,70.7547)) V(ResdetId,bookingdate,Amount,AmountExcl))
SELECT ResdetId,Amount,AmountExcl,
       MIN(bookingdate) AS MinBookingDate,
       MAX(bookingdate) AS MaxBookingDate
FROM VTE
GROUP BY ResdetId,Amount,AmountExcl;

正如我的萨米人所说,我读错了结果,这是一个差距和岛屿问题:

WITH VTE AS(
    SELECT ResdetId,
           CONVERT(date,bookingdate) AS bookingdate,
           Amount,
           AmountExcl
    FROM (VALUES (120106,'20180204',75.00,70.7547),
                 (120106,'20180205',75.00,70.7547),
                 (120106,'20180206',90.00,84.9057),
                 (120106,'20180208',75.00,70.7547),
                 (120106,'20180209',75.00,70.7547)) V(ResdetId,bookingdate,Amount,AmountExcl)),
Grps AS(
    SELECT *,
           ROW_NUMBER() OVER (PARTITION BY ResdetId ORDER BY V.bookingdate) - 
           ROW_NUMBER() OVER (PARTITION BY ResdetId, Amount ORDER BY V.bookingdate) AS Grp
    FROM VTE V)
SELECT ResdetId,
       Amount,
       AmountExcl,
       MIN(bookingdate) AS MinBookingDate,
       MAX(bookingdate) AS MaxBookingDate
FROM Grps
GROUP BY ResdetId,
         Amount,
         AmountExcl,
         Grp
ORDER BY ResdetId,
         Amount,
         MinBookingDate;
于 2018-08-28T08:47:12.390 回答
0

您没有看到 2018-02-07 因为 bookingdate 不在您的分区中所以

|ResdetId | Amount | AmountExcl 
--------------------------------
|120106   | 75.00  |  70.7547   
|120106   | 90.00  |  84.9057   

您的分区是唯一的。所以它就像一把钥匙。您需要另一个属性来区分相同的数据:

|ResdetId | Amount | AmountExcl 
--------------------------------
|120106   | 75.00  |  70.7547 
于 2018-08-28T08:43:38.083 回答
0

试试这个,它使用行号差异技术:

declare @tbl table(ResdetId int, bookingdate date, Amount float, AmountExcl float);
insert into @tbl values
(120106   , '2018-02-04'  ,  75.00 ,  70.7547   ),
(120106   , '2018-02-05'  ,  75.00 ,  70.7547   ),
(120106   , '2018-02-06'  ,  90.00 ,  84.9057   ),
(120106   , '2018-02-08'  ,  75.00 ,  70.7547   ),
(120106   , '2018-02-09'  ,  75.00 ,  70.7547   );

select MIN(bookingDate), MAX(bookingDate), Amount, AmountExcl
from (
    select *,
           ROW_NUMBER() over (order by bookingDate) -
           ROW_NUMBER() over (partition by amount, AmountExcl order by bookingDate) rn
    from @tbl
) a group by Amount, AmountExcl, rn
于 2018-08-28T09:24:33.060 回答