2017-06-22 223 views
3

我將達到一個月內服務使用的總天數。 (開始日期和結束日期是 - 包括兩端)如何查找一個月內使用的天數總數?

示例數據1:

User Start_Date  End_Date 
A  01-Jun-2017 30-Jun-2017 
B  06-Jun-2017 30-Jun-2017 

答案:服務使用天= 30天。

示例數據2:

User Start_Date  End_Date 
C  06-Jun-2017 10-Jun-2017 
D  02-Jun-2017 02-Jun-2017 

答案:服務使用天= 6天。

我該如何編寫代碼來查找相同的SQL語言,更適合PLSQL。

+0

你能解釋一下所需的邏輯嗎? –

+0

Didnt理解邏輯推導(服務使用天)。用戶'A'的樣本數據爲30天,但B爲25天。在你的問題中,你剛剛提到了30' –

+0

,你解釋了它是結束日期和開始日期之間的基本區別,或者沒有正確解釋。 從表中選擇用戶,(end_date - start_date)作爲「Service Used」。 –

回答

3

測試數據

CREATE TABLE your_table (usr, start_date, end_date) AS (
    SELECT 'A', DATE '2017-06-01', DATE '2017-06-03' FROM DUAL UNION ALL 
    SELECT 'B', DATE '2017-06-02', DATE '2017-06-04' FROM DUAL UNION ALL -- Overlaps previous 
    SELECT 'C', DATE '2017-06-06', DATE '2017-06-06' FROM DUAL UNION ALL 
    SELECT 'D', DATE '2017-06-07', DATE '2017-06-07' FROM DUAL UNION ALL -- Adjacent to previous 
    SELECT 'E', DATE '2017-06-11', DATE '2017-06-20' FROM DUAL UNION ALL 
    SELECT 'F', DATE '2017-06-14', DATE '2017-06-15' FROM DUAL UNION ALL -- Within previous 
    SELECT 'G', DATE '2017-06-22', DATE '2017-06-25' FROM DUAL UNION ALL 
    SELECT 'H', DATE '2017-06-24', DATE '2017-06-28' FROM DUAL UNION ALL -- Overlaps previous and next 
    SELECT 'I', DATE '2017-06-27', DATE '2017-06-30' FROM DUAL UNION ALL 
    SELECT 'J', DATE '2017-06-27', DATE '2017-06-28' FROM DUAL;   -- Within H and I   

查詢

SELECT SUM(days) AS total_days 
FROM (
    SELECT dt - LAG(dt) OVER (ORDER BY dt) + 1 AS days, 
     start_end 
    FROM (
    SELECT dt, 
      CASE SUM(value) OVER (ORDER BY dt ASC, value DESC, ROWNUM) * value 
      WHEN 1 THEN 'start' 
      WHEN 0 THEN 'end' 
      END AS start_end 
    FROM your_table 
    UNPIVOT (dt FOR value IN (start_date AS 1, end_date AS -1)) 
) 
    WHERE start_end IS NOT NULL 
) 
WHERE start_end = 'end'; 

輸出

TOTAL_DAYS 
---------- 
     25 

說明

SELECT dt, value 
FROM your_table 
UNPIVOT (dt FOR value IN (start_date AS 1, end_date AS -1)) 

這將UNPIVOT表,以便開始和結束日期是在同一列(dt)和給出的相應值開始時爲+1,結束日期爲-1。

SELECT dt, 
     SUM(value) OVER (ORDER BY dt ASC, value DESC, ROWNUM) AS total, 
     value 
FROM your_table 
UNPIVOT (dt FOR value IN (start_date AS 1, end_date AS -1)) 

將給出這些生成值的開始和結束日期以及累計總和。範圍的起始位置始終爲value=1total=1,範圍的末尾始終爲total=0。如果日期在一個範圍的中間,那麼它將有total>1value=-1total=1。使用此項,如果乘以valuetotal,則範圍的開始爲value*total=1,範圍的結尾爲value*total=0,而其他任何值指示範圍中途的日期。

這是什麼這給出:

SELECT dt, 
     CASE SUM(value) OVER (ORDER BY dt ASC, value DESC, ROWNUM) * value 
     WHEN 1 THEN 'start' 
     WHEN 0 THEN 'end' 
     END AS start_end 
FROM your_table 
UNPIVOT (dt FOR value IN (start_date AS 1, end_date AS -1)) 

然後,您可以過濾掉的日期時start_endNULL這會讓你有一張桌子交替startend行,您可以使用LAG計算天差數:

SELECT dt - LAG(dt) OVER (ORDER BY dt) + 1 AS days, 
     start_end 
FROM (
    SELECT dt, 
     CASE SUM(value) OVER (ORDER BY dt ASC, value DESC, ROWNUM) * value 
      WHEN 1 THEN 'start' 
      WHEN 0 THEN 'end' 
     END AS start_end 
    FROM your_table 
    UNPIVOT (dt FOR value IN (start_date AS 1, end_date AS -1)) 
) 
WHERE start_end IS NOT NULL 

所有你需要做的就是SUM全部爲end - start的差異;它給出了上面的查詢。

+0

您完全理解我的要求@ MT0。測試案例不會更好。謝謝冠軍。 – Raghu

+0

優秀的竅門VALUE * TOTAL –

+0

嘿,你能幫我做下面的代碼: (兩行的開始和/或結束日期相同) SET 1: A 1-Jun- 2017年3月-2017 B 1-君-2017 2-君2017 結果:NULL 預期的結果:3 SET 2: A 1君-2017 3君2017 B 1-Jun- 2017 3-Jun-2017 結果:1 預期結果:3 – Raghu

1

由於@Pravin Satav解決,您的要求,這是不是很清楚,這樣的事情是我從你的描述可以理解:

SELECT sum(CASE WHEN end_date=start_date THEN 1 ELSE (end_date-start_date)+1 END) as total_days 
FROM my_table 
WHERE <conditions that determine your "sample data">; 
+0

這不包括兩個(或更多)範圍重疊時的重複計數天數。 – MT0

+0

必須是不能從OP中所述的要求中明確表示的。 –

+0

那麼OP在示例數據1示例中指出結果應該是30天 - 您的答案會給出30 + 25 = 55天。 – MT0

相關問題