2015-09-25 3 views
0

Я хочу оценить, выполняются ли определенные условия, а затем возвращать определенный текст. Я использую синтаксис 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;           
+0

Что значит не работает? Какая ошибка? Для этого скрипта установите флажки в скобках. Кроме того, если инструкции 'CASE/WHEN' становятся сложными, рассмотрите возможность использования запросов UNION. Если это не производительность, это может помочь, по крайней мере, для удобства чтения и обслуживания. – Parfait

+0

@Parfait Извините, я должен настроить то, что я сказал раньше. Что происходит в части «Задержка», оно должно проверять начальное условие (часть u.first_name) и затем проверять, соответствует ли оно любому из условий, указанных ниже (после части AND). Я думаю, что я ошибся в своем первоначальном описании вопроса, кажется, что запрос не учитывает часть AND, а не только конечный критерий, упомянутый в моем первоначальном вопросе. – Mischa

+0

@Патрик извиняется, полный запрос добавлен сейчас. – 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_id и od.preorder.

Смежные вопросы