与我发布的另一个问题类似,如下表所示......
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。但是,我无法弄清楚这项工作的语法。
答案 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