【问题标题】:Combining two tables with date ranges into one table将两个具有日期范围的表合并到一个表中
【发布时间】:2018-08-01 21:26:20
【问题描述】:

作为我处理电信数据计费工作的一部分,我从各种来源收集数据以构建准确的成本核算系统。目前,一张表从监管电子表格中获取数据,另一张表从各种定价表中获取数据——这些都是在电话号码范围内键入的,例如

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 语句和一些连接?

【问题讨论】:

  • 到底在做什么?您没有向我们清楚地描述导致该输出的规则。 “基于日期范围如何重叠”并没有真正将其作为需求的定义,其中可能存在一些歧义。

标签: sql sql-server join inner-join


【解决方案1】:

您可以尝试使用JOIN on during date 和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 |

【讨论】:

  • 那是小伙子。在我编写 SQL 查询的所有时间里,我从未考虑过在 ON 语句中使用 OR。非常感谢。
  • @TonyMoore 很高兴为您提供帮助 :)
【解决方案2】:

怎么样:

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');

然后,[short] 查询:

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

【讨论】:

    【解决方案3】:

    从 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)
    

    【讨论】:

      猜你喜欢
      • 2017-12-07
      • 2017-08-17
      • 1970-01-01
      • 1970-01-01
      • 2022-08-17
      • 1970-01-01
      • 2011-02-04
      • 1970-01-01
      • 2015-10-31
      相关资源
      最近更新 更多