2017-08-28 37 views
1

我在嘗試將MS-Access查詢轉換爲postgres語句,以便我可以在SSRS中使用它。似乎工作很好,除了IIF聲明。IIF in postgres

SELECT labor_sort_1.ncm_id 
,IIf(labor_sort_1.sortby_employeeid = 3721 
, ((labor_sort_1.MaxUpdatedAt - labor_sort_1.MinNCMScanTime) * 24 * 29 * labor_sort_1.number_of_ops) 
, IIf(labor_sort_1.sortby_employeeid = 3722 
    , ((labor_sort_1.MaxUpdatedAt - labor_sort_1.MinNCMScanTime) * 24 * 24 * labor_sort_1.number_of_ops) 
    , IIf(labor_sort_1.sortby_employeeid = 3755, ((labor_sort_1.MaxUpdatedAt - labor_sort_1.MinNCMScanTime) * 24 * 24 * labor_sort_1.number_of_ops) 
    , ((labor_sort_1.MaxUpdatedAt - labor_sort_1.MinNCMScanTime) * 24 * 17 * labor_sort_1.number_of_ops)))) AS labor_cost 
FROM 
(SELECT 
ls_sort.ncm_id 
, ls_sort.computer_name 
, ls_sort.number_of_ops 
, ls_sort.badge_scan_time 
, ls_sort.sortby_employeeid 
, Min(ls_sort.ncm_scan_time) AS MinNCMScanTime 
, Max(ls_sort.updated_at) AS MaxUpdatedAt 
FROM stone.ls_sort 
INNER JOIN stone.ls ON ls_sort.ls_id = ls.ls_id 
WHERE 1=1 
AND ls_sort.created_at Between current_date-1 And current_date 
GROUP BY ls_sort.ncm_id 
, ls_sort.computer_name 
, ls_sort.number_of_ops 
, ls_sort.badge_scan_time 
, ls_sort.sortby_employeeid 
ORDER BY ls_sort.computer_name) AS labor_sort_1 

它返回以下消息 function iif(boolean, interval, interval) does not exist 我將如何解決這個問題?

回答

5

您需要將邏輯切換到CASE語句。 CASE語句對於大多數RDBMS是標準的,所以值得學習。在你的情況(雙關語意),它會轉換成:

CASE 
    WHEN labor_sort_1.sortby_employeeid = 3721 
     THEN (labor_sort_1.MaxUpdatedAt - labor_sort_1.MinNCMScanTime) * 24 * 29 * labor_sort_1.number_of_ops 
    WHEN labor_sort_1.sortby_employeeid = 3722 
     THEN (labor_sort_1.MaxUpdatedAt - labor_sort_1.MinNCMScanTime) * 24 * 24 * labor_sort_1.number_of_ops 
    WHEN labor_sort_1.sortby_employeeid = 3755 
     THEN (labor_sort_1.MaxUpdatedAt - labor_sort_1.MinNCMScanTime) * 24 * 24 * labor_sort_1.number_of_ops 
    ELSE 
     (labor_sort_1.MaxUpdatedAt - labor_sort_1.MinNCMScanTime) * 24 * 17 * labor_sort_1.number_of_ops) 
    END AS labor_cost 

這是很多清潔期待,因爲你不必用嵌套iif()問題猴和這一切,你應該需要添加更多的僱員的到硬編碼勞動力成本清單,這並不是什麼大問題。

您也可以在這裏找到對我們有利的IN條件,所以你只需要兩個WHEN條款:

CASE 
    WHEN labor_sort_1.sortby_employeeid = 3721 
     THEN (labor_sort_1.MaxUpdatedAt - labor_sort_1.MinNCMScanTime) * 24 * 29 * labor_sort_1.number_of_ops 
    WHEN labor_sort_1.sortby_employeeid IN (3722, 3755) 
     THEN (labor_sort_1.MaxUpdatedAt - labor_sort_1.MinNCMScanTime) * 24 * 24 * labor_sort_1.number_of_ops 
    ELSE 
     (labor_sort_1.MaxUpdatedAt - labor_sort_1.MinNCMScanTime) * 24 * 17 * labor_sort_1.number_of_ops) 
    END AS labor_cost 

此外,您可以移動CASE語句插入的公式,只是把出什麼號碼,你希望乘以:

(labor_sort_1.MaxUpdatedAt - labor_sort_1.MinNCMScanTime) 
    * 24  
    * CASE 
     WHEN labor_sort_1.sortby_employeeid = 3721 THEN 29 
     WHEN labor_sort_1.sortby_employeeid IN (3722,3755) THEN 24 
     ELSE 17 
     END 
    * labor_sort_1.number_of_ops AS labor_cost 
+0

非常棒的建議+1並標記爲答案,但是。有沒有辦法在postgres中創建函數pg_temp函數,其行爲與ms訪問中的iif行爲相同? (對於我的老闆) –

+1

我不熟悉postgres的功能來說這是否可能。我認爲這將是,但我會避免這樣做的原因有兩個:1)iif()對於RDBMSs來說是一個古怪的球。每個在陽光下的RDBMS都使用CASE。爲了讓你的SQL更加標準化,切換到CASE將是一個好主意。 2)我敢打賭,UDF會比RDBMS邏輯中深陷於CASE的東西慢。 – JNevill

+0

非常感謝。我做了一些調整,現在它正在生產中。 –