2015-09-25 102 views
0

我想评估是否符合某些条件,然后返回某个文本。我使用CASE语法,但我不完全确定这是否是最实际的方法。此外,因为某些条件必须匹配附加条件(WHEN语句返回'延迟')。尽管它看起来很杂乱,但它确实有效,除了'延迟'声明中的最后一条标准。CASE声明中的多个条件

这是我目前的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;           
+0

你是什么意思不起作用?什么是错误?对于这个脚本,检查括号对齐。另外,如果'CASE/WHEN'语句变得错综复杂,请考虑使用UNION查询。如果不是为了提高性能,至少可以提高可读性和可维护性。 – Parfait

+0

@Parfait对不起,我必须调整我刚才说的。 '延迟'部分会发生什么,它应该检查初始条件(u.first_name部分),然后检查它是否也符合下面提到的任何条件(在AND部分之后)。我认为我在对问题的初始描述中犯了一个错误,似乎查询并未考虑AND部分,而不仅仅是我原来的问题中提到的最终标准。 – Mischa

+0

@Patrick道歉,现在完整查询。 – Mischa

回答

1

这是很难肯定对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中的字符串。