给定一列有效日期,是否有可以将其转换为日期范围的SQL语句?

时间:2016-08-23 11:39:37

标签: sql sqlite range

与我发布的另一个问题类似,如下表所示......

Promo   EffectiveDate
------   -------------
PromoA  1/1/2016
PromoB  4/1/2016
PromoC  7/1/2016
PromoD  10/1/2016
PromoE  1/1/2017

将其转换为开始日期和结束日期的最简单方法是什么,如此......

Promo   StartDate  EndDate
------  ---------  ---------
PromoA  1/1/2016   4/1/2016
PromoB  4/1/2016   7/1/2016
PromoC  7/1/2016   10/1/2016
PromoD  10/1/2016  1/1/2017
PromoE  1/1/2017   null (ongoing until a new Effective Date is added)

更新

相关查询似乎是最简单的解决方案,但据我所知,它们效率极低,因为子查询必须在外部选择的每一行运行一次。

我认为潜在的解决方案是第二次从表中选择值,但是消除了第一个结果,然后通过简单的左外连接将它们与序数索引的第一个选择配对

作为一个例子,用字母代替上面的日期,第一个选择将是A,B,C,D,E,第二个将是B,C,D,E(这是第一个选择减去第一个记录' A')然后通过序数索引与简单的左外连接将它们配对,得到AB,BC,CD,DE,E-null。但是,我无法弄清楚这项工作的语法。

3 个答案:

答案 0 :(得分:2)

相关的子查询可以查找您需要的其他字段。

SELECT
    yourTable.*,
    (
    SELECT MIN(lookup.EffectiveDate)
      FROM yourTable   AS lookup
     WHERE lookup.EffectiveDate > yourTable.EffectiveDate
    )
FROM
    yourTable

<强> 修改

“每行必须运行一次”的概念是对SQL如何生成实际运行的执行计划的误解。将一个表连接到另一个表也可以这样说,连接必须每行至少运行一次......相关的子查询确实有更大的成本,但是使用适当的索引它不会“极高“,并且描述的功能确实有效。

如果 另一个字段 保证是顺序的,那么这将是微不足道的,但 尝试重新使用现有的促销字段以实现其他目的。

SELECT
    this.*,
    next.EffectiveEpoch
FROM
    yourTable    this
LEFT JOIN
    yourTable    next
        ON  next.sequential_id = this.sequential_id + 1

答案 1 :(得分:1)

是的,您可以使用SELECT t.promo,t.effectiveDate as start_date, (SELECT s.effectiveDate FROM YourTable s WHERE s.date > t.date ORDER BY s.effectiveDate LIMIT 1) as end_date FROM YourTable t 的相关查询:

SELECT t.promo,t.effectiveDate as start_date,
       MIN(s.effectiveDate) as end_date
FROM YourTable t
LEFT JOIN YourTable s
 ON(t.date < s.date)
GROUP BY t.promo,t.effectiveDate

编辑:以下是一个包​​含联接的解决方案:

{{1}}

答案 2 :(得分:0)

显示这一点,使用子查询

select
p.promo,
p.EffectiveDate as "Start",
(select n.EffectiveDate from table_promo n where n.EffectiveDate > 
p.EffectiveDate order by n.EffectiveDate limit 1) as "End"
from table_promo p