从日期匹配的其他行中获取值

时间:2017-06-09 12:22:41

标签: sql sql-server

我有一个SQL查询问题。我在SQL Server 2014中有下表。

declare @t table (STORE_ID int, INDEX_ID int, START_DATE datetime,
              END_DATE datetime, 
              GROSS_SALES_PRICE decimal(10,2),
              NET_SALES_PRICE INT 
             );

insert into @t 
values (3,22,'2014-08-01 00:00:00.000', '2014-09-30 23:59:59.000', 29.99,25),
       (3,22,'2014-10-01 00:00:00.000', '2014-12-31 23:59:59.000', NULL,NULL),
       (3,22,'2015-01-01 00:00:00.000', '2015-09-30 23:59:59.000', 39.99,28),
       (4,22,'2016-01-01 00:00:00.000', '2016-07-31 23:59:59.000', 29.99,25),
       (4,22,'2016-08-01 00:00:00.000', '2016-12-31 23:59:59.000', NULL,NULL),
       (4,22,'2017-01-01 00:00:00.000', '2018-09-30 23:59:59.000', 39.99,28),
       (1,22,'2014-08-30 00:00:00.000', '2014-10-31 23:59:59.000', 39.99,28),
       (1,22,'2014-11-01 00:00:00.000', '2016-09-30 23:59:59.000', 20.99,15)

正如您所看到的,某些行中的GROSS_SALES_PRICENET_SALES_PRICE中有一些NULLS。这种情况是从STORE_ID等于1的行中获取此价格。例如,如果您在第二行中有NULL值,则可以从商店编号1中获取此价格的价格。但是在此类型中您有2种不同的价格。因此,您必须将该NULL行拆分为两行,并采用两种不同的价格。如果peroid没有加工部分,则行的一部分应保留为NULL。所有日期都是可分的。结果应该是这样的。

declare @t2 table (STORE_ID int, INDEX_ID int, START_DATE datetime,
              END_DATE datetime, 
              GROSS_SALES_PRICE decimal(10,2),
              NET_SALES_PRICE INT 
             );

insert into @t2 
values (3,22,'2014-08-01 00:00:00.000', '2014-09-30 23:59:59.000', 29.99,25),
       (3,22,'2014-10-01 00:00:00.000', '2014-10-31 23:59:59.000', 39.99,28),
       (3,22,'2014-11-01 00:00:00.000', '2014-12-31 23:59:59.000', 20.99,15),
       (3,22,'2015-01-01 00:00:00.000', '2015-09-30 23:59:59.000', 39.99,28),
       (4,22,'2016-01-01 00:00:00.000', '2016-07-31 23:59:59.000', 29.99,25),
       (4,22,'2016-08-01 00:00:00.000', '2016-09-30 23:59:59.000', 20.99,15),
       (4,22,'2016-10-01 00:00:00.000', '2016-12-31 23:59:59.000', NULL,NULL),
       (4,22,'2017-01-01 00:00:00.000', '2018-09-30 23:59:59.000', 39.99,28),
       (1,22,'2014-08-30 00:00:00.000', '2014-10-31 23:59:59.000', 39.99,28),
       (1,22,'2014-11-01 00:00:00.000', '2016-09-30 23:59:59.000', 20.99,15)

1 个答案:

答案 0 :(得分:1)

日历/日期表可以简化此操作,但我们也可以使用查询使用common table expression生成临时日期表。

加入来自index_id的每个store_id 1的价格加上日期表,我们可以加入并汇总以获取缺失值的价格。然后使用union all返回价格行,以及我们尝试填写价格的行:

/* -- dates --*/
declare @fromdate datetime, @thrudate datetime;
select  @fromdate = min(start_date), @thrudate = max(end_date) from @t;
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, dates as (
  select top (datediff(day, @fromdate, @thrudate)+1) 
      [Date]=convert(datetime,dateadd(day,row_number() over(order by (select 1))-1,@fromdate))
    , [End_Date]=convert(datetime,dateadd(second,-1,dateadd(day,row_number() over(order by (select 1)),@fromdate)))
  from n as deka cross join n as hecto cross join n as kilo
                 cross join n as tenK cross join n as hundredK
   order by [Date]
)
/* -- default price -- */
, cte as (
select 
    d.index_id
  , start_date = d.date
  , end_date   = d.end_date
  , t.gross_sales_price
  , t.net_sales_price
from (
  select dates.*
    , i.index_id
  from dates 
    cross join (select distinct index_id from @t) i
    ) d
  left join (select * from @t where store_id = 1) t
    on d.date >= t.start_date
   and d.date <= t.end_date
   and d.index_id = t.index_id
)
/* -- rows with a price */
select
    t.store_id
  , t.index_id
  , start_date
  , end_date
  , gross_sales_price
  , net_sales_price
from @t t
where t.Gross_Sales_Price is not null
union all 
/* -- rows with with a null price */
select 
    t.store_id
  , t.index_id
  , start_date = min(d.start_date)
  , end_date   = max(d.end_date)
  , gross_sales_price = d.gross_sales_price
  , net_sales_price = d.net_sales_price
from @t t
  left join cte d
    on t.index_id = d.index_id
   and d.start_date >= t.start_date 
   and d.end_date   <= t.end_date
where t.Gross_Sales_Price is null
group by 
    t.store_id, t.index_id, d.gross_sales_price, d.net_sales_price
order by store_id, index_id

rextester演示:http://rextester.com/QXDNF59094

返回:

+----------+----------+-------------------------+-------------------------+-------------------+-----------------+
| store_id | index_id |       start_date        |        end_date         | gross_sales_price | net_sales_price |
+----------+----------+-------------------------+-------------------------+-------------------+-----------------+
|        1 |       22 | 2014-08-30 00:00:00.000 | 2014-10-31 23:59:59.000 | 39.99             | 28              |
|        1 |       22 | 2014-11-01 00:00:00.000 | 2016-09-30 23:59:59.000 | 20.99             | 15              |
|        3 |       22 | 2014-11-01 00:00:00.000 | 2014-12-30 23:59:59.000 | 20.99             | 15              |
|        3 |       22 | 2014-10-01 00:00:00.000 | 2014-10-31 23:59:59.000 | 39.99             | 28              |
|        3 |       22 | 2014-08-01 00:00:00.000 | 2014-09-30 23:59:59.000 | 29.99             | 25              |
|        3 |       22 | 2015-01-01 00:00:00.000 | 2015-09-30 23:59:59.000 | 39.99             | 28              |
|        4 |       22 | 2016-01-01 00:00:00.000 | 2016-07-31 23:59:59.000 | 29.99             | 25              |
|        4 |       22 | 2017-01-01 00:00:00.000 | 2018-09-30 23:59:59.000 | 39.99             | 28              |
|        4 |       22 | 2016-10-01 00:00:00.000 | 2016-12-30 23:59:59.000 | NULL              | NULL            |
|        4 |       22 | 2016-08-01 00:00:00.000 | 2016-09-30 23:59:59.000 | 20.99             | 15              |
+----------+----------+-------------------------+-------------------------+-------------------+-----------------+

日历和数字表参考: