PostFres中的IIF

时间:2017-08-28 13:13:23

标签: postgresql

我正在尝试将MS-Access查询转换为postgres语句,以便我可以在SSRS中使用它。除了IIF声明外,似乎工作得很好。

.Site {
  display: flex;
  min-height: 100vh;
  flex-direction: column;
}

.Site-content {
  flex: 1;
}

它返回以下消息  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 我该如何解决这个问题?

3 个答案:

答案 0 :(得分:11)

您需要将逻辑切换为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

答案 1 :(得分:1)

与@Daniel的答案相同,但可以推广到任何数据类型。

CREATE or replace FUNCTION iIF(
    condition boolean,       -- IF condition
    true_result anyelement,  -- THEN
    false_result anyelement  -- ELSE
) RETURNS anyelement AS $f$
  SELECT CASE WHEN condition THEN true_result ELSE false_result END
$f$  LANGUAGE SQL IMMUTABLE;

SELECT iif(0=1,1,2);
SELECT iif(0=0,'Hello'::text,'Bye');  -- need to say that string is text.

寻找public-snippets-library时很好。

答案 2 :(得分:0)

我知道这已经存在了一段时间,但是另一个选择是创建用户定义的函数。如果您在互联网搜索中偶然发现此问题,那么这可能是您的解决方案。

    CREATE FUNCTION IIF(
        condition boolean, true_result TEXT, false_result TEXT
    ) RETURNS TEXT LANGUAGE plpgsql AS $$
    BEGIN
     IF condition THEN
        RETURN true_result;
     ELSE
        RETURN false_result;
     END IF;
    END
    $$;

    SELECT IIF(2=1,'dan the man','false foobar');

如果文本不让您喜欢,请尝试函数重载