2016-10-21 132 views
1

我試圖找到一個查詢,該查詢會給出範圍在另一個範圍內的天數。例如,讓我們說有一個叫日期如何使用SQL查找範圍在另一個範圍內的天數

 UID SmallRangeStart smallRangeEnd  BigRangeStart  BigRangeEnd 
     1  01 15 2016  01 20 2016  01 17 2016   02 30 2016 

所以我想返回3,因爲小範圍落在3天的大範圍內的...有一個查詢,能做到這一點的表?

+0

您使用的(MySQL和SQL Server等)什麼版本的SQL的? –

+0

首先確保你使用,你使用的是哪個DBMS日期數據類型 – Strawberry

+0

存儲日期?那一排是4列嗎?還是分佈在2列和2列?或者4行1列?另外:'02 30 2016'是無效日期。有沒有2月30日 –

回答

0

要使用的邏輯是,如果兩個範圍完全不相交,則重疊爲零。如果小範圍開始並結束BigRangeStart或小範圍開始並結束BigRangeEnd後會發生這種情況。否則,如果確實發生了某些重疊,那麼您希望獲得SmallRangeEndBigRangeEnd較大的SmallRangeStartBigRangeStart較小的

這裏是一個MySQL的解決方案:

SELECT CASE WHEN SmallRangeEnd < BigRangeStart THEN 0 
      WHEN SmallRangeStart > BigRangeEnd THEN 0 
      ELSE DATEDIFF(GREATEST(SmallRangeStart, BigRangeStart), 
          LEAST(SmallRangeEnd, BigRangeEnd)) 
     END AS days_in_range 
FROM yourTable 

查詢也遷移到SQL Server時,並沒有太大變化:

SELECT CASE WHEN SmallRangeEnd < BigRangeStart THEN 0 
      WHEN SmallRangeStart > BigRangeEnd THEN 0 
      ELSE DATEDIFF(day, 
          CASE WHEN SmallRangeStart > BigRangeStart 
           THEN SmallRangeStart ELSE BigRangeStart END, 
          CASE WHEN SmallRangeEnd < BigRangeEnd 
           THEN SmallRangeEnd ELSE BigRangeEnd END) 
     END AS days_in_range 
FROM yourTable 
+0

謝謝你這工作! – daf3131

1

對於MySQL數據庫,你可以使用DATEDIFF函數

 select datediff('2016-09-15','2016-09-12') 
這個查詢將返回3

對於MSSQL數據庫,你可以使用(只扣除)

SELECT DATEDIFF(day,'2007-05-06 12:10:09','2007-05-07 12:10:09') 

它將返回1

對於Oracle您可以使用

SELECT TO_DATE('2000-01-02', 'YYYY-MM-DD') - 
    TO_DATE('2000-01-01', 'YYYY-MM-DD') AS DateDiff 

FROM雙

對於PostgreSQL:可以使用

SELECT DATE_PART('day', '2011-12-31 01:00:00'::timestamp - '2011-12-29 23:00:00'::timestamp); 

- 這將返回:1

0

這是Postgres的範圍類型的完美契合:

假設你有一個單排四列,首先計算這兩個範圍的交集,使用:

daterange(smallrangestart, smallrangeend) * daterange(bigrangestart, bigrangeend) as overlap 

這給出了兩個範圍的重疊。從新的範圍,你簡單地從上限減去下界

上(重疊) - 下(重疊);

所以整個語句應該是:

select upper(daterange(smallrangestart, smallrangeend) * daterange(bigrangestart, bigrangeend)) - 
     lower(daterange(smallrangestart, smallrangeend) * daterange(bigrangestart, bigrangeend)) 
from the_table 
where uid = 1;