【问题标题】:SQL Query Startdate to EnddateSQL 查询开始日期到结束日期
【发布时间】:2014-03-07 10:32:31
【问题描述】:

我有一张这样的表(例如TableA

|姓名 |开始日期 |结束日期    |
|----------------------------------------------|
|一个     | 2014-02-26 | 2014-02-28 |
| b     | 2014-03-05 | 2014-03-06 |

如果我想低于结果。请帮忙怎么办?

|姓名 |日期   |
|---------------------------------------|
|一个  | 2014-02-26 |
|一个  | 2014-02-27 |
|一个  | 2014-02-28 |
| b                                               2014-03-05 |
| b                                               2014-03-06 |

谢谢。

【问题讨论】:

  • 你的数据库是哪个? sql server、oracle、MySql等?
  • 明确你的问题....我想你说的是从开始日期到结束日期从列开始日期和结束日期获取结果。使用 SP 增加 startdate 并检查
  • 这个问题并没有真正说明您正在寻找什么样的查询。据我所知,您需要每个名称的开始日期和结束日期之间的所有日期。对吗?
  • ...你有日历表吗?如果是,这很简单。

标签: sql


【解决方案1】:

在 Oracle 中有点棘手:

SELECT distinct b.name, trim(regexp_substr(b.dates, '[^,]+', 1, LEVEL)) day
  FROM 
  (
    select a.name name,(select WM_CONCAT(a.startdate + rownum -1)  from all_objects  where rownum <=    a.enddate - a.startdate + 1) dates
    from TableA a
  ) b
CONNECT BY LEVEL <= length(b.dates) - length(REPLACE(b.dates, ',', ''))+1
order by 1,2;

内部查询为每个名称生成天数作为逗号分隔的字符串。外部只是将字符串拆分为几行。

【讨论】:

  • ....真的吗?虽然我不怀疑这行得通,但它不太可能是一个高性能的选择。
【解决方案2】:

在 SQL Server 中可以使用CTE 来实现,如下所示

;WITH cte(name, Startdate,Enddate)
AS
(  
    SELECT name, Startdate,Enddate FROM your_table
    UNION ALL
    SELECT name, DATEADD(dd, 1,Startdate),Enddate FROM CTE 
    WHERE Startdate < Enddate
)
SELECT * FROM cte ORDER BY name

这是SQL Fiddle的代码

【讨论】:

  • 使用递归 CTE 不是在 SQL Server 中生成系列的好方法。尽管在这个规模上它不太可能引起很多问题,但使用基于集合的逻辑仍然会更好。见 - Generate a set or sequence without loops – part 2
  • @GarethD 我们会将 CTE 视为一个循环吗?循环肯定会影响性能,但就我的经验而言,CTE 的性能非常好
  • 我认为递归 CTE 是一个 while 循环,因为它会在返回结果时继续执行递归成员,尽管这是语义。阅读我发布的文章,或者至少向下滚动到性能比较,它显示递归 CTE 比下一个最慢的方法慢 15 倍以上。
  • 这是我的第一条评论。
【解决方案3】:

这是一个简单的方法

select name, startdate from test_table
UNION ALL 
select name, enddate from test_table
order by 2 desc 

【讨论】:

  • 这只是获取开始日期和结束日期,而不是两者之间的日期。例如对于示例数据中的a,这将不包括2014-02-27