複雜sql處理邏輯 case when的用法

2021-01-08 我的華仔部落

場景:

實習計劃中,包括輪換計劃,個人計劃。輪換計劃之間不會存在時間疊加。個人計劃於輪換計劃之間可能會存在時間疊加。疊加部分以個人計劃為準。計劃狀態包括:未開始,實習中,實習中斷,實習結束。 狀態根據開始時間,結束時間與當前時間的關係來計算。但是需要通過sql處理,疊加狀態時間判斷。

圖例:

假如當前系統時間是2019-11-26,序號3的狀態應該為實習中,序號4的狀態應該為實習中斷。

假如當前系統時間為2019-11-29,序號2的狀態是實習中,序號3的狀態是實習結束,序號4的狀態是實習中斷。

假如當前系統時間為2019-12-01,序號2的狀態是實習結束,序號3的狀態是實習結束,序號4的狀態是實習中。

說明:

1、當是個人計劃時,只要當前系統時間是處於該計劃的範圍內,該計劃就是實習中。(比如圖一、圖二)

2、當是輪換計劃時,要分時間考慮。如果該時間段內,且是當前系統時間所處的時間範圍,沒有其他個人計劃時,該輪換計劃就是實習中。(比如上圖三)而改時間段內,是當前系統時間所處時間範圍,有其他個人計劃時,該輪換計劃就是實習中斷。(比如上圖一、圖二)

背景:

後臺採用三個表trainee_info 實習生表 trainee_rotation_program 計劃表 trainee_group_info 輪換分組表

計劃表中存在 trainee_id 實習生id 、group_id 分組id 、plan_type 計劃類型

計劃類型為1或者為null的是輪換計劃,關聯分組id 計劃類型為2的是個人計劃,關聯實習生id

資料庫保存的時間格式是 年月日 時分秒的 但是時分秒全都是0 比如2019-11-26 00:00:000

所以寫sql判斷時間時要注意時分秒的處理

sql:

select a.name,c.structure_name as dept_name,b.starttime,b.endtime, ( <!-- 第一種情況 個人計劃 只要當前時間在範圍內 優先個人計劃 個人計劃實習中--> <!-- 第二種情況 輪科計劃 當前時間在範圍內,且當前時間 存在其他個人計劃優先於輪科計劃 輪科計劃 實習中斷 --> <!-- 第三種情況 輪科計劃 當前時間在範圍內,且當前時間 不存在其他個人計劃優先輪科計劃的情況 輪科計劃 實習中 --> <!-- 第四種情況 任何計劃 當前時間小於開始時間 未開始--> <!-- 第五種情況 任何計劃 當前時間大於結束時間 實習結束--> <![CDATA[ case when b.plan_type='2' and DATEADD(DAY,1,b.endtime) > GETDATE() and GETDATE() > b.starttime then 1 when (b.plan_type is null or b.plan_type='1') and DATEADD(DAY,1,b.endtime) > GETDATE() and GETDATE() > b.starttime and ( select count(1) from ( select * from trainee_rotation_program t where (t.trainee_id =a.id) and ( (b.starttime <= t.starttime and t.starttime <= b.endtime) or (t.endtime >= b.starttime and t.endtime <= b.endtime) or (t.starttime >= b.starttime and t.endtime <= b.endtime) ) and (DATEADD(DAY,1,t.endtime) > GETDATE() and GETDATE() > t.starttime) ) aa )>0 then 3 when (b.plan_type is null or b.plan_type='1') and DATEADD(DAY,1,b.endtime) > GETDATE() and GETDATE() > b.starttime and ( select count(1) from ( select * from trainee_rotation_program t where (t.trainee_id =a.id) and ( (b.starttime <= t.starttime and t.starttime <= b.endtime) or (t.endtime >= b.starttime and t.endtime <= b.endtime) or (t.starttime >= b.starttime and t.endtime <= b.endtime) ) and (DATEADD(DAY,1,t.endtime) > GETDATE() and GETDATE() > t.starttime) ) aa )=0 then 1 when GETDATE() < b.starttime then 0 when GETDATE() > DATEADD(DAY,1,b.endtime) then 2 else 2 end ]]> ) curstate, a.starttime as userstar,a.endtime as userend,b.plan_type as plan_type, (case when (b.plan_type=1 or b.plan_type is null) then '輪換計劃('+g.name+')' when b.plan_type=2 then '個人計劃' else '' end) as planSource, orderid from trainee_info a LEFT JOIN trainee_rotation_program b on (a.group_id = b.group_id or b.trainee_id=a.id) left join trainee_group_info g on b.group_id = g.id LEFT JOIN org_structure c on b.dept_id=c.id where a.id=#{id} and b.endtime>a.starttime order by orderid,b.starttime desc <!-- 先根據排序號排序,再根據開始時間排序,用於個人計劃的插單排序 -->查詢sql結果:(id=63)

關鍵部分解析以及思路:

1、由於優先個人計劃,先判斷個人計劃類型,以及當前系統時間在範圍內,注意時分秒的處理,返回1表示進行中。

2、判斷輪換計劃,實習中斷的情況。首先類型是輪換計劃,再篩選是否存在同時間段內,符合條件的個人計劃 如果存在,則說明是實習中斷狀態。返回3表示實習中斷。

判斷條件包括 個人計劃;開始時間在範圍中,或者結束時間在範圍中,或者開始時間結束時間都在範圍中;當前系統是否處於該範圍。

以圖一為例 使用case when 判斷序號4的狀態 序號4的開始時間為 2019-04-01 結束時間為 2020-01-02 當前系統時間為2019-11-26

上述系統中,存在一條序號3的記錄滿足判斷條件 序號3的開始時間為 2019-11-26 結束時間為 2019-11-28 屬於開始時間結束時間都處於序號4的範圍內,且當前系統時間也處於序號3的 範圍內

3、判斷輪換計劃,實習中的情況。首先類型是輪換計劃,再篩選2中相同的條件,如果不存在記錄,則說明是實習中。返回1表示實習中。

以圖三為例 使用case when 判斷序號4的狀態 序號4的開始時間為 2019-04-01 結束時間為 2020-01-02 當前系統時間為2019-12-01

上述系統中,存在序號2 序號3滿足時間範圍的條件,2019-11-26到2019-11-28 2019-11-29到2019-11-30 都屬於開始時間結束時間都處於序號4的範圍內,但不滿足當前系統時間範圍的條件

4、判斷任何計劃,只要當前系統時間比開始時間小,都返回0,表示未開始。

5、判斷任何計劃,只要當前系統時間比結束時間大,都返回2,表示實習結束。

相關焦點

  • case的用法,in case (of), in no case, it's the case都要會用
    今天我們來學習case的用法。請熟讀例句到會說:01case病例;情況;案件;真相; 箱Set my case over the shelves.把我的箱子放在架子上。Can you cite another case like this one?你能舉出另一個像這樣的案例嗎?She gave an accurate account of the case.她對情況作了準確的敘述。I think it's a case of sour grapes.
  • 經典SQL面試題及答案分析
    when語法。SELECT a.c_id,b.c_name,MAX(score),MIN(score),ROUND(AVG(score),2), ROUND(100*(SUM(case when a.score>=60 then 1 else 0 end)/SUM(case when a.score then 1 else 0 end)),2) as 及格率, ROUND(100*(SUM(case
  • 英語高頻考點:in case 詳解
    一、考點說明  高考對in case的考查,通常會將其與其他用法相似的結構結合在一起綜合考查。同學們在做這類題時,關鍵的是要能正確理解各個選項的意思,然後結合題幹所給定的上下文語境進行綜合理解,最後選出一個意思最恰當的選項。如:  1.
  • 大數據分析工程師入門9-Spark SQL
    大數據處理使用SQL進行大數據處理,使傳統的RDBMS人員也可以進行大數據處理,不需要掌握像mapreduce的編程方法。Long) // 通過反射轉換為DataSetval caseClassDS = Seq(Person("Andy",32)).toDS()caseClassDS.show()// +----+---+// |name|age|// +----+---+// |Andy| 32|// +----+---+// DataFrame指定一個類則為DataSetval path = "examples/src
  • 主管對員工說Make a strong case是什麼意思?
    Case很常出現在辦公室口語中,用法靈活,意思很多。我們來看幾個容易誤解的句子。1.That will be the case.錯誤:就是這個案子。正確:情況就是這樣了。英文的名詞多半有「實」和「虛」兩種含義。 Case實的含義是「外殼、箱子」,虛的則是「情況、案件」。 "That will be the case.
  • 四級完形填空應考技巧及邏輯關係詞彙總結
    分析認識文章結構,理解領會文章各部分、各層次之間的邏輯關係。  只有明白文章結構,了解各段落之間的關係,才能加深對文章的理解。明白了各部分是如何為表現主題思想服務的,也就更容易把握帶空的句子所需要的是什麼內容,因此就更容易選準答案了。這要求考生具有紮實的英語詞組、短語、習慣用法等英語搭配的知識,這對於理解文章的邏輯關係特別有利。
  • 英語in case of 和 in the case of 的區別
    英語中,in case of 和 in the case of 是兩個常用且相似的詞組,但是它們的用法並不相同,今天我們一起來學習一下。1. in case of:這個詞組意為「萬一;一旦」。例句1:It would be safer to take more money with you in case of emergency.多帶點錢保險些,以防急用。例句2:You'd better take an umbrella just in case of rain.以防下雨,你最好帶把傘。
  • 最詳細的SQL注入相關的命令整理
    cscript c:\inetpub\adminscripts\adsutil.vbs enum w3svc/2/root >c:\test1.txt (將2換成1、3、4、5試試)type c:\test1.txtdel c:\test1.txt在NBSI下可以直接顯示運行結果,所以不用導出到文件2)在網站上隨便找到一個圖片的名字 123.jpg然後寫進批處理程序
  • sqltoy-orm-4.16.11 發版,部分功能優化
    開源地址:更新內容1、修復#[and @loop(:params,' status=':params[i]'','or')] 處理後#[]中沒有參數導致被整體剔除的缺陷2、增加convertType(pageModel
  • PandaSQL:一個讓你能夠通過SQL語句進行pandas的操作的python包
    如果你熟練的使用SQL,那麼這篇文章將介紹一種更直接、簡單的使用Pandas處理大多數數據操作案例。假設你對SQL非常的熟悉,或者你想有更可讀的代碼。或者您只是想在dataframe上運行一個特殊的SQL查詢。或者,也許你來自R,想要一個sqldf的替代品。
  • ved in the case that
    Jarndyce is deeplyinvolved in the case that bears his name and that willsupposedly settle an estate in which he has an interest.
  • 這個函數讓SQL效率提升99%
    指定按其執行窗口函數計算的邏輯順序。order_by_expression 指定用於進行排序的列或表達式。order_by_expression 只能引用可供 FROM 子句使用的列 。不能將整數指定為表示列名或別名。
  • Oracle分組查詢group by的用法及講解
    group by是sql中比較強大的功能,是在對數據分組統計時必不可少的用法。但是,對於很多經驗不足的同學,經常會寫錯。今天我們就以Oracle為例,來講解下分組查詢group by的用法。我們接下來使用下聚合函數SELECT SSEX,MAX(SAGE) FROM STUDENT GROUP BY SSEX;注意這條sql語句,select子句中聚合函數使用了SAGE(年齡)這個欄位,那會不會違背了前面所說的 「select子句後的欄位必須來自group by後的分組欄位」這個規律呢,我們來執行一下:能正常執行,成功地按照了性別分組,並且查詢出了性別對應年齡最大的學生
  • Mybatis中SqlSource解析流程詳解
    前面幾篇文章都在詳細分析mapper的加載過程,但是始終沒有看到sql的解析過程,今天來詳細分析下。在處理的過程中如果遇到if、foreach等節點還會把contents傳遞進去,從上面的圖中可以看到ForEachHandler、IfHandler處理器也會調用parseDynamicTags方法生成MixedSqlNode然後再生成對應的SqlNode放到contents中。
  • 大數據分析工程師面試集錦3-SQL/SparkSql/HiveQL
    (3)SQL雖然看上去很簡單,但實際上是一種強有力的語言,靈活使用其語言元素,可以進行非常複雜和高級的資料庫操作。題2:你是怎麼理解資料庫和表的?答:資料庫是一個以某種有組織的方式存儲的數據集合。答:SELECTcase when prod_price between 1 and 10 then '1~10'when prod_price between 11 and 100 then '11~100'
  • mysql 資料庫group_concat函數的一些用法
    對於group_contact函數一般懂一點sql的人來說,並不算太陌生,它主要配合group by 使用,起著分組時,將涉及行的相應的欄位串聯成一個欄位如下表a:我們按照type分類,並將對應的名稱按逗號分隔保存為一個names欄位可以寫為:select type,group_concat(name) names from a group by
  • RNA生物計算機實現複雜邏輯計算
    RNA生物計算機實現複雜邏輯計算 來源:中科院生物科技戰略情報   發布者:尹海華   日期:2017-08-11   今日/總瀏覽:3/5267
  • 春眠不覺曉,SQL 知多少?|原力計劃
    SQL/MDA 允許存儲、訪問和處理規模的多維數組,例如 N 通道的衛星圖像。這意味著 SQL 現在可以解碼圖像,並且通過像素坐標直接訪問和處理圖像區域。多態表函數:不需要預先定義返回類型的表函數,允許開發人員利用動態 SQL 創建強大而複雜的自定義函數。新的數據類型 DECFLOAT。
  • SQL Server 首次登陸 Linux 平臺
    藉助這個特性,數據科學家直接操作處理儲存在 SQL Server 的數據,不用數據遷移了。機器學習/數據科學領域內的另一種程式語言 R,SQL Server 在去年就整合了。更多細節,見 SQL Server 官方:https://www.microsoft.com/en-us/sql-server/sql-server-2017參考:VentureBeta、SQL Server看完本文有收穫?