将两个具有日期范围的表合并为一个表

时间:2018-08-01 21:26:20

标签: sql sql-server

作为我对电信数据计费的一部分,我从各种来源抓取了数据,以建立一个准确的成本核算系统。当前,一个表从监管电子表格中获取数据,而另一个表则从各种定价表中获取数据-这些都是在电话号码范围内输入的,例如

Table 1  (Range, Provider, Status, Valid From, Valid To)
'0113', 'BT', 'Allocated', '2018-01-01 00:00:00', '2018-07-14 23:59:59'
'0113', 'BT2', 'Allocated', '2018-07-15 00:00:00', '2299-12-31 23:59:59'

Table 2  (Range, Price Band, Valid From, Valid To)
'0113', 'Price1', '2018-01-01 00:00:00', '2018-06-30 23:59:59'
'0113', 'Price2', '2018-07-01 00:00:00', '2299-12-31 23:59:59'

Output Table
'0113', 'BT', 'Allocated', 'Price1', '2018-01-01 00:00:00', '2018-06-30 23:59:59'
'0113', 'BT', 'Allocated', 'Price2', '2018-07-01 00:00:00', '2018-07-14 23:59:59'
'0113', 'BT2', 'Allocated', 'Price2', '2018-07-15 00:00:00', '2299-12-31 23:59:59'

现在,我可以使用游标遍历第一个表,然后从第二个表中选择记录,并根据日期范围如何相互重叠输出一系列行来做到这一点,但是有一种简单的方法一个SQL语句和一些联接?

3 个答案:

答案 0 :(得分:5)

您可以尝试在日期期间使用JOIN,并在CASE WHEN子句中使用SELECT判断日期。

SELECT T1.Range,
      T1.Provider,
      T1.Status, 
      T2.[Price Band],
      CASE WHEN T1.[Valid From] >= T2.[Valid From] THEN T1.[Valid From]
           ELSE T2.[Valid From] END,
      CASE WHEN T1.[Valid To] <= T2.[Valid To] THEN T1.[Valid To]
           ELSE T2.[Valid To] END
FROM T1 INNER JOIN T2 on 
(
    T1.[Valid From] between T2.[Valid From] and T2.[Valid To] 
OR
    T1.[Valid To] between T2.[Valid From] and T2.[Valid To]
) 
AND 
   T1.Range =T2.Range

sqlfiddle

[结果]

| Range | Provider |    Status | Price Band |           Valid From |             Valid To |
|-------|----------|-----------|------------|----------------------|----------------------|
|  0113 |       BT | Allocated |     Price1 | 2018-01-01T00:00:00Z | 2018-06-30T23:59:59Z |
|  0113 |       BT | Allocated |     Price2 | 2018-07-01T00:00:00Z | 2018-07-14T23:59:59Z |
|  0113 |      BT2 | Allocated |     Price2 | 2018-07-15T00:00:00Z | 2299-12-31T23:59:59Z |

答案 1 :(得分:0)

怎么样:

create table table1 (
  range varchar(50),
  provider varchar(50),
  status varchar(50),
  valid_from datetime,
  valid_to datetime
);

insert into table1 (range, provider, status, valid_from, valid_to) 
  values ('0113', 'BT', 'Allocated', '2018-01-01 00:00:00', 
          '2018-07-14 23:59:59');
insert into table1 (range, provider, status, valid_from, valid_to) 
   values ('0113', 'BT2', 'Allocated', '2018-07-15 00:00:00', 
          '2299-12-31 23:59:59');

create table table2 (
  range varchar(50),
  price_band varchar(50),
  valid_from datetime,
  valid_to datetime
);

insert into table2 (range, price_band, valid_from, valid_to) 
  values ('0113', 'Price1', '2018-01-01 00:00:00', '2018-06-30 23:59:59');
insert into table2 (range, price_band, valid_from, valid_to) 
  values ('0113', 'Price2', '2018-07-01 00:00:00', '2299-12-31 23:59:59');

然后是[简短]查询:

select
   t1.range, t1.provider, t2.price_band, 
   iif(t1.valid_from > t2.valid_from, t1.valid_from, t2.valid_from) as valid_from,
   iif(t1.valid_to < t2.valid_to, t1.valid_to, t2.valid_to) as valid_to
  from table1 t1, table2 t2
  where t1.valid_from between t2.valid_from and t2.valid_to
     or t1.valid_to between t2.valid_from and t2.valid_to

结果:

range  provider  price_band  valid_from             valid_to
-----  --------  ----------  ---------------------  ---------------------
0113   BT        Price1      2018-01-01 00:00:00.0  2018-06-30 23:59:59.0
0113   BT        Price2      2018-07-01 00:00:00.0  2018-07-14 23:59:59.0
0113   BT2       Price2      2018-07-15 00:00:00.0  2299-12-31 23:59:59.0

答案 2 :(得分:0)

缺少where的情况:如果t2中的日期范围完全包含在t1范围中.....

where t1.valid_from between t2.valid_from and t2.valid_to
     or t1.valid_to between t2.valid_from and t2.valid_to
     or (t1.valid_to < t2.valid_to and t1.valid_from > t2.valid_from)