CASE语句中的多个条件

时间:2015-09-25 03:09:41

标签: postgresql

我想评估某些条件是否得到满足,然后返回某个文本。我正在使用CASE语法,但我不完全确定这是否是最实用的方法。还因为某些条件必须匹配其他条件(返回'延迟'的WHEN语句)。即使它看起来很混乱,但它确实有效,除了“延迟”声明中的最后一个标准。

这是我目前的CASE声明:

    CASE
    WHEN
    (stf.status_id IN ('38','14','13','12','16','18') AND stf.date >= (p.fecha_prevista_entrega + INTERVAL '30 minutes')) 
    OR (stf.status_id IN ('38','14','13','12','16','18') AND stf.date < (os.rider_accepted + INTERVAL '5 minutes'))
    THEN 'Not Paid - Cancelled' 

    WHEN
    (stf.status_id IN ('38','14','13','12','16','18') AND stf.date <= (p.fecha_prevista_entrega + INTERVAL '30 minutes')) 
    AND (stf.status_id IN ('38','14','13','12','16','18') AND stf.date >= p.fecha_entrega_repartidor)
    THEN 'Paid - Cancelled'

    WHEN
    (u.first_name ILIKE '%LKF%' AND ((EXTRACT(HOUR FROM os.food_delivered - p.fecha_prevista_entrega)*60+EXTRACT(MINUTE FROM os.food_delivered - p.fecha_prevista_entrega)+EXTRACT(SECOND FROM os.food_delivered - p.fecha_prevista_entrega)/60) > '15'))
    OR (u.first_name NOT ILIKE '%LKF%' AND ((EXTRACT(HOUR FROM os.food_delivered - p.fecha_prevista_entrega)*60+EXTRACT(MINUTE FROM os.food_delivered - p.fecha_prevista_entrega)+EXTRACT(SECOND FROM os.food_delivered - p.fecha_prevista_entrega)/60) > '30'))

    AND (
    ((od.preorder = '0' AND od.order_comment ILIKE '%' || u.first_name || '%') AND (EXTRACT(HOUR FROM os.rider_assigned - od.date)*60+EXTRACT(MINUTE FROM os.rider_assigned - od.date)+EXTRACT(SECOND FROM os.rider_assigned - od.date)/60) < '15')

    OR        
    ((od.preorder = '0' AND od.order_comment NOT ILIKE '%' || u.first_name || '%') AND (EXTRACT(HOUR FROM os.rider_assigned - od.date)*60+EXTRACT(MINUTE FROM os.rider_assigned - od.date)+EXTRACT(SECOND FROM os.rider_assigned - od.date)/60) < '20')

    OR
    (od.preorder = '1' AND (EXTRACT(HOUR FROM p.fecha_prevista_entrega - os.rider_assigned)*60+EXTRACT(MINUTE FROM p.fecha_prevista_entrega - os.rider_assigned)+EXTRACT(SECOND FROM p.fecha_prevista_entrega - os.rider_assigned)/60) > '30')

    OR
    ((EXTRACT(HOUR FROM os.food_delivered - p.fecha_prevista_entrega)*60+EXTRACT(MINUTE FROM os.food_delivered - p.fecha_prevista_entrega)+EXTRACT(SECOND FROM os.food_delivered - p.fecha_prevista_entrega)/60) > '15')

    OR
    ((os.rider_at_restaurant >= (p.fecha_entrega_repartidor + INTERVAL '3 minutes')) AND ((EXTRACT(HOUR FROM os.food_picked_up - p.fecha_entrega_repartidor)*60+EXTRACT(MINUTE FROM os.food_picked_up - p.fecha_entrega_repartidor)+EXTRACT(SECOND FROM os.food_picked_up - p.fecha_entrega_repartidor)/60) < '15'))


    )
    THEN 'Delay'

    ELSE 'None' END AS payment_adj

该声明的这一部分不起作用:

    OR
    ((os.rider_at_restaurant >= (p.fecha_entrega_repartidor + INTERVAL '3 minutes')) AND ((EXTRACT(HOUR FROM os.food_picked_up - p.fecha_entrega_repartidor)*60+EXTRACT(MINUTE FROM os.food_picked_up - p.fecha_entrega_repartidor)+EXTRACT(SECOND FROM os.food_picked_up - p.fecha_entrega_repartidor)/60) < '15'))

我已经交叉检查了几个显示“延迟”的结果,但不应该显示它,因为它们不符合这个条件。

这是完整的查询

WITH order_steps AS                         
(                       
    SELECT pedido_id,                       
    MAX(CASE WHEN situacion  = 0 THEN created_at END) AS rider_assigned,                        
    MAX(CASE WHEN situacion  = 1 THEN created_at END) AS rider_viewed,                      
    MAX(CASE WHEN situacion  = 2 THEN created_at END) AS rider_accepted,                        
    MAX(CASE WHEN situacion  = 3 THEN created_at END) AS         rider_at_restaurant,                       
    MAX(CASE WHEN situacion  = 4 THEN created_at END) AS food_picked_up,                        
    MAX(CASE WHEN situacion  = 5 THEN created_at END) AS rider_at_customer,                     
    MAX(CASE WHEN situacion  = 6 THEN created_at END) AS food_delivered,                        
    MAX(CASE WHEN situacion  = 10 THEN created_at END) AS unknown_status                        
    FROM dwh.tracking_motero t                      
    GROUP BY 1                      
    ORDER BY 1,2                        
),                      
    assigned_riders AS (                        
    WITH rider_assignments AS (                     
    SELECT mp.pedido_id, mp.motero_id, mp.created_at, ROW_NUMBER() OVER (PARTITION BY mp.pedido_id ORDER BY mp.created_at DESC) AS last_assignments                     
    FROM dwh.motero_pedido mp                       
    )                       
    SELECT pedido_id, motero_id FROM rider_assignments                      
    WHERE last_assignments = 1                      
    )                       

    SELECT 
    CASE
    WHEN
    (stf.status_id IN ('38','14','13','12','16','18') AND stf.date >= (p.fecha_prevista_entrega + INTERVAL '30 minutes')) 
    OR (stf.status_id IN ('38','14','13','12','16','18') AND stf.date < (os.rider_accepted + INTERVAL '5 minutes'))
    THEN 'Not Paid - Cancelled' 

    WHEN
    (stf.status_id IN ('38','14','13','12','16','18') AND stf.date <= (p.fecha_prevista_entrega + INTERVAL '30 minutes')) 
    AND (stf.status_id IN ('38','14','13','12','16','18') AND stf.date >= p.fecha_entrega_repartidor)
    THEN 'Paid - Cancelled'

    WHEN
    (u.first_name ILIKE '%LKF%' AND ((EXTRACT(HOUR FROM os.food_delivered - p.fecha_prevista_entrega)*60+EXTRACT(MINUTE FROM os.food_delivered - p.fecha_prevista_entrega)+EXTRACT(SECOND FROM os.food_delivered - p.fecha_prevista_entrega)/60) > '15'))
    OR (u.first_name NOT ILIKE '%LKF%' AND ((EXTRACT(HOUR FROM os.food_delivered - p.fecha_prevista_entrega)*60+EXTRACT(MINUTE FROM os.food_delivered - p.fecha_prevista_entrega)+EXTRACT(SECOND FROM os.food_delivered - p.fecha_prevista_entrega)/60) > '30'))

    AND (
    ((od.preorder = '0' AND od.order_comment ILIKE '%' || u.first_name || '%') AND (EXTRACT(HOUR FROM os.rider_assigned - od.date)*60+EXTRACT(MINUTE FROM os.rider_assigned - od.date)+EXTRACT(SECOND FROM os.rider_assigned - od.date)/60) < '15')

    OR        
    ((od.preorder = '0' AND od.order_comment NOT ILIKE '%' || u.first_name || '%') AND (EXTRACT(HOUR FROM os.rider_assigned - od.date)*60+EXTRACT(MINUTE FROM os.rider_assigned - od.date)+EXTRACT(SECOND FROM os.rider_assigned - od.date)/60) < '20')

    OR
    (od.preorder = '1' AND (EXTRACT(HOUR FROM p.fecha_prevista_entrega - os.rider_assigned)*60+EXTRACT(MINUTE FROM p.fecha_prevista_entrega - os.rider_assigned)+EXTRACT(SECOND FROM p.fecha_prevista_entrega - os.rider_assigned)/60) > '30')

    OR
    ((EXTRACT(HOUR FROM os.food_delivered - p.fecha_prevista_entrega)*60+EXTRACT(MINUTE FROM os.food_delivered - p.fecha_prevista_entrega)+EXTRACT(SECOND FROM os.food_delivered - p.fecha_prevista_entrega)/60) > '15')

    OR
    ((os.rider_at_restaurant >= (p.fecha_entrega_repartidor + INTERVAL '3 minutes')) AND ((EXTRACT(HOUR FROM os.food_picked_up - p.fecha_entrega_repartidor)*60+EXTRACT(MINUTE FROM os.food_picked_up - p.fecha_entrega_repartidor)+EXTRACT(SECOND FROM os.food_picked_up - p.fecha_entrega_repartidor)/60) < '15'))


    )
    THEN 'Delay'



    ELSE 'None' END AS payment_adj,
    p.id AS urban_ninja_id,                         
    o.order_fp_code AS order_code,                      
    p.total AS order_amount,                        
    p.paymenttype_name,                     
    u.first_name AS rider_code,                     
    p.direccion AS delivery_address,                        
    p.fecha_entrega_repartidor AS expected_pick_up_time,                        
    p.fecha_prevista_entrega AS expected_delivery_time,                     
    od.date AS order_creation_date,                     
    os.rider_assigned,                      
    os.rider_viewed,                        
    os.rider_accepted,                      
    os.rider_at_restaurant,                     
    os.food_picked_up,                      
    os.rider_at_customer,                       
    os.food_delivered,                      
    os.unknown_status,                      
    st.id AS status_id,                     
    st.code AS status_code,                     
    st.title AS status,                     
    ve.title AS vendor,                     
    EXTRACT(HOUR FROM os.rider_assigned-od.date)*60+EXTRACT (MINUTE FROM os.rider_assigned-od.date)+EXTRACT (SECOND FROM os.rider_assigned-od.date)/60 AS dispatching_time,                     
    EXTRACT(HOUR FROM os.rider_viewed-os.rider_assigned)*60+EXTRACT (MINUTE FROM os.rider_viewed-os.rider_assigned)+EXTRACT (SECOND FROM os.rider_viewed-os.rider_assigned)/60 AS rider_reaction_time,                      
    EXTRACT(HOUR FROM os.rider_accepted-os.rider_viewed)*60+EXTRACT (MINUTE FROM os.rider_accepted-os.rider_viewed)+EXTRACT (SECOND FROM os.rider_accepted-os.rider_viewed)/60 AS rider_acceptance_time,                        
    EXTRACT(HOUR FROM os.rider_at_restaurant-os.rider_accepted)*60+EXTRACT (MINUTE FROM os.rider_at_restaurant-os.rider_accepted)+EXTRACT (SECOND FROM os.rider_at_restaurant-os.rider_accepted)/60 AS rider_driving_to_restaurant_time,                        
    EXTRACT(HOUR FROM os.food_picked_up-os.rider_at_restaurant)*60+EXTRACT (MINUTE FROM os.food_picked_up-os.rider_at_restaurant)+EXTRACT (SECOND FROM os.food_picked_up-os.rider_at_restaurant)/60 AS rider_in_restaurant_time,                        
    EXTRACT(HOUR FROM os.rider_at_customer-os.food_picked_up)*60+EXTRACT (MINUTE FROM os.rider_at_customer-os.food_picked_up)+EXTRACT (SECOND FROM os.rider_at_customer-os.food_picked_up)/60 AS rider_driving_to_customer_time,                        
    EXTRACT(HOUR FROM os.food_delivered-os.rider_at_customer)*60+EXTRACT (MINUTE FROM os.food_delivered-os.rider_at_customer)+EXTRACT (SECOND FROM os.food_delivered-os.rider_at_customer)/60 AS rider_at_customer_time,                        
    EXTRACT (HOUR FROM os.food_delivered-od.date)*60 + EXTRACT (MINUTE FROM os.food_delivered-od.date) + EXTRACT (SECOND FROM os.food_delivered-od.date)/60 AS delivery_time,                       
    od.order_comment,                       
    od.preorder                     
    FROM dwh.pedido p                       
    LEFT JOIN dwh.order_fp o ON p.id = o.pedido_id                      
    LEFT JOIN order_steps os ON os.pedido_id = p.id                     
    LEFT JOIN assigned_riders r ON r.pedido_id = p.id                       
    LEFT JOIN dwh.moteros m ON m.id = r.motero_id                       
    LEFT JOIN dwh.sf_guard_user u ON u.id = m.sf_guard_user_id                      
    INNER JOIN dwh."Orders" od ON od.id = o.order_fp_id                     
    INNER JOIN dwh."Status" st ON st.id = od.status_id
    INNER JOIN dwh."Statusflows" stf ON stf.order_id = od.id
    INNER JOIN dwh."Vendors" ve ON od.vendor_id = ve.id                     
    WHERE u.first_name NOT IN ('TEST RIDER','Jan')                      
    and os.rider_accepted between (current_date-30) and (current_date-1)        
   GROUP BY p.id, stf.status_id, stf.date, os.rider_accepted, u.first_name, os.food_delivered, od.preorder, od.order_comment, os.rider_assigned, od.date, os.food_picked_up, os.rider_at_restaurant, o.order_fp_code, os.rider_viewed, os.rider_at_customer, os.unknown_status, st.id, ve.title
   LIMIT 100;                                           

1 个答案:

答案 0 :(得分:2)

很难确定CASE子句中的逻辑,但至少下面的内容应该有效,因为它在语法上是正确的:

WITH order_steps AS (       
  SELECT pedido_id,
    max(CASE WHEN situacion =  0 THEN created_at END) AS rider_assigned,
    max(CASE WHEN situacion =  1 THEN created_at END) AS rider_viewed,
    max(CASE WHEN situacion =  2 THEN created_at END) AS rider_accepted,
    max(CASE WHEN situacion =  3 THEN created_at END) AS rider_at_restaurant,
    max(CASE WHEN situacion =  4 THEN created_at END) AS food_picked_up,
    max(CASE WHEN situacion =  5 THEN created_at END) AS rider_at_customer,
    max(CASE WHEN situacion =  6 THEN created_at END) AS food_delivered,
    max(CASE WHEN situacion = 10 THEN created_at END) AS unknown_status
  FROM dwh.tracking_motero
  GROUP BY 1
), assigned_riders AS (
  WITH rider_assignments AS (                     
    SELECT pedido_id, motero_id, created_at,
           ROW_NUMBER() OVER (PARTITION BY pedido_id ORDER BY created_at DESC) AS rn
    FROM dwh.motero_pedido
  )
  SELECT pedido_id, motero_id FROM rider_assignments WHERE rn = 1
)
SELECT 
  CASE
    WHEN
         (stf.status_id IN ('38','14','13','12','16','18') AND stf.date >= (p.fecha_prevista_entrega + interval '30 minutes')) 
      OR (stf.status_id IN ('38','14','13','12','16','18') AND stf.date < (os.rider_accepted + interval '5 minutes'))
    THEN 'Not Paid - Cancelled' 

    WHEN
         (stf.status_id IN ('38','14','13','12','16','18') AND stf.date <= (p.fecha_prevista_entrega + interval '30 minutes')) 
      OR (stf.status_id IN ('38','14','13','12','16','18') AND stf.date >= p.fecha_entrega_repartidor)
    THEN 'Paid - Cancelled'

    WHEN
        (
           (u.first_name ILIKE '%LKF%'     AND extract(epoch from os.food_delivered - p.fecha_prevista_entrega) > 900)
        OR (u.first_name NOT ILIKE '%LKF%' AND extract(epoch from os.food_delivered - p.fecha_prevista_entrega) > 1800)
        )
      AND (
        (od.preorder = '0' AND od.order_comment ILIKE '%' || u.first_name || '%'
         AND extract(epoch from os.rider_assigned - od.date) < 900)
        OR
        (od.preorder = '0' AND od.order_comment NOT ILIKE '%' || u.first_name || '%' 
         AND extract(epoch from os.rider_assigned - od.date) < 1200)
        OR
        (od.preorder = '1' AND extract(epoch from p.fecha_prevista_entrega - os.rider_assigned) > 1800)
        OR
        (extract(epoch from os.food_delivered - p.fecha_prevista_entrega) > 900)
        OR
        (extract(epoch from os.rider_at_restaurant - p.fecha_entrega_repartidor) > 180)
         AND extract(epoch from os.food_picked_up - p.fecha_entrega_repartidor) < 900)
      )
    THEN 'Delay'
    ELSE 'None' END AS payment_adj,
    p.id AS urban_ninja_id, 
    o.order_fp_code AS order_code,      
    p.total AS order_amount,
    p.paymenttype_name,     
    u.first_name AS rider_code,     
    p.direccion AS delivery_address,
    p.fecha_entrega_repartidor AS expected_pick_up_time,
    p.fecha_prevista_entrega AS expected_delivery_time,     
    od.date AS order_creation_date,     
    os.rider_assigned,      
    os.rider_viewed,
    os.rider_accepted,      
    os.rider_at_restaurant,     
    os.food_picked_up,      
    os.rider_at_customer,       
    os.food_delivered,      
    os.unknown_status,      
    st.id AS status_id,     
    st.code AS status_code,     
    st.title AS status,     
    ve.title AS vendor,     
    to_date(os.rider_assigned - od.date, 'HH24:MI:SS') AS dispatching_time,     
    to_date(os.rider_viewed - os.rider_assigned, 'HH24:MI:SS') AS rider_reaction_time,      
    to_date(os.rider_accepted - os.rider_viewed, 'HH24:MI:SS') AS rider_acceptance_time,
    to_date(os.rider_at_restaurant - os.rider_accepted, 'HH24:MI:SS') AS rider_driving_to_restaurant_time,
    to_date(os.food_picked_up - os.rider_at_restaurant, 'HH24:MI:SS') AS rider_in_restaurant_time,
    to_date(os.rider_at_customer - os.food_picked_up, 'HH24:MI:SS') AS rider_driving_to_customer_time,
    to_date(os.food_delivered - os.rider_at_customer, 'HH24:MI:SS') AS rider_at_customer_time,
    to_date(os.food_delivered - od.date, 'HH24:MI:SS') AS delivery_time,       
    od.order_comment,       
    od.preorder     
FROM dwh.pedido p       
LEFT JOIN dwh.order_fp o ON p.id = o.pedido_id      
LEFT JOIN order_steps os ON os.pedido_id = p.id     
LEFT JOIN assigned_riders r ON r.pedido_id = p.id       
LEFT JOIN dwh.moteros m ON m.id = r.motero_id       
LEFT JOIN dwh.sf_guard_user u ON u.id = m.sf_guard_user_id      
JOIN dwh."Orders" od ON od.id = o.order_fp_id     
JOIN dwh."Status" st ON st.id = od.status_id
JOIN dwh."Statusflows" stf ON stf.order_id = od.id
JOIN dwh."Vendors" ve ON od.vendor_id = ve.id     
WHERE u.first_name NOT IN ('TEST RIDER','Jan')      
  AND os.rider_accepted BETWEEN (current_date-30) AND (current_date-1)
GROUP BY p.id, stf.status_id, stf.date, os.rider_accepted, u.first_name, os.food_delivered, od.preorder,
         od.order_comment, os.rider_assigned, od.date, os.food_picked_up, os.rider_at_restaurant,
         o.order_fp_code, os.rider_viewed, os.rider_at_customer, os.unknown_status, st.id, ve.title
LIMIT 100;

同时查看extract()混乱的“快捷方式”:extract (epoch from time2 - time1)给出间隔中的秒数。在CASE子句中,我将您的分钟转换为秒,在选择列表中,我使用to_date()函数来获得良好的显示。

同时检查您的数据类型,您似乎隐含地将integer值转换为字符串,如stf.status_idod.preorder