SQL:从多个开始日期和结束日期获取范围日期

时间:2013-10-08 15:03:40

标签: sql sql-server

如何从多个dateBegin和dateEnd获取“max”范围的日期?我的问题没有得到很好的解释(因为我不是英文),但下面的例子将告诉你我的期望。

我的数据库:

enter image description here

我想要的输出:

id_master    beginDate    endDate
13           26/07/2014   30/08/2014
280          28/09/2013   01/10/2013
280          01/04/2014   11/04/2014

解释:对于不同的id_master,我希望有不同的日期时段由最小的beginDate和最大的endDate组成,并且这些日期之间的所有日期都有一个产品(表中的行)

当前查询:

SELECT DISTINCT campings.id_master, CAST(campings.dateBegin AS DATETIME) AS beginDate, CAST(campings.dateEnd AS DATETIME) AS endDate
FROM         campings 
ORDER BY id_master, beginDate, endDate

PS:日期格式为dd / mm / yyyy

3 个答案:

答案 0 :(得分:3)

这可能比以前更加人为,而其他人可以提出更简单的答案,但您可以尝试以下内容:

WITH ordered AS (
  SELECT a.id_master, a.beginDate, a.endDate, 
      ROW_NUMBER() OVER(PARTITION BY id_master ORDER BY beginDate, endDate) AS rn
  FROM Table1 a
), Adjacent AS (
  SELECT a.id_master, a.beginDate, a.endDate, a.rn
  FROM ordered a
  UNION ALL
  SELECT a.id_master, a.beginDate, b.endDate, b.rn
  FROM Adjacent a
  INNER JOIN ordered b ON a.id_master = b.id_master AND b.rn > a.rn 
      AND a.endDate >= b.beginDate
), resolvedEnd AS (
  SELECT a.id_master, a.beginDate, MAX(a.endDate) AS endDate
  FROM Adjacent a
  GROUP BY a.id_master, a.beginDate
)
SELECT a.id_master, MIN(beginDate) AS beginDate, endDate
FROM resolvedEnd a
GROUP BY a.id_master, a.endDate

SQL Fiddle example

这样做首先在每行附加一个递增的行号,以确保我们只向前递送。然后,它设置递归CTE以关联重叠的行(以及重叠行的重叠行)。然后它会解析每个开始日期的最大结束日期,然后解析每个结束日期的最早开始日期。

答案 1 :(得分:0)

对于其他人来说,这是我目前需求的结果。在 Informix 11.70 及以上版本中,此结构具有相同的结果:


SELECT id_master , MIN(beginDate) AS beginDate, endDate FROM
  LATERAL (
    SELECT id_master, beginDate, MAX(endDate) AS endDate FROM
      LATERAL (
        SELECT id_master, beginDate, CONNECT_BY_ROOT endDate FROM
          LATERAL (
            SELECT id_master, beginDate, endDate, ROW_NUMBER() OVER(PARTITION BY id_master ORDER BY beginDate, endDate) AS row_num FROM campings
          ) AS ordered
          CONNECT BY
            PRIOR id_master = id_master AND
            PRIOR row_num > row_num AND
            PRIOR endDate + 1 >= beginDate AND
            PRIOR beginDate - 1 <= endDate
      ) AS Adjacent
      GROUP BY id_master, beginDate
  ) AS resolvedEnd
  GROUP BY id_master, endDate

答案 2 :(得分:-1)

SELECT DISTINCT 
    id_master, 
    MIN (beginDate) OVER (PARTION BY id_master) beginDate, 
    MAX(endDate) OVER (PARTION BY id_master) endDate 
FROM campings