2016-10-22 6 views
3

Пройдите эту отредактированную таблицу.Как вычесть даты двух столбцов в sql

enter image description here

Вы можете предположить, order_header_key в порядке нет.

Я хочу, чтобы получить список того NOS, чей текущий статус 3 и предыдущее состояние было 2, и дата состояния (СОСТОЯНИЕ 3) -status дата (2) < = 3 дней для этого порядка

в следующая таблица для заказа «даты (состояние 3)» не-1 - «дата (состояние 2) = 20 октября - 19 октября , который менее чем за 3 дня -> Так действует порядка

но для заказа 3 'дата (статус 3)' - 'дата (статус 2)' = 30 OCT - 24 OCT , срок действия которого составляет более 3 дней

заказ № 2 в недействителен, так как статусы 3 и 1, 2 отсутствует

ответ

3

Предполагая, что заказ не может иметь более одной записи на комбинацию order_no/статуса, вы могли бы присоединиться два подзапроса:

SELECT s3.order_no 
FROM (SELECT * 
     FROM orders 
     WHERE status = 3) s3 
JOIN (SELECT * 
     FROM orders 
     WHERE status = 2) s2 ON s3.order_no = s2.order_no AND 
           s3.status_date - s3.status_date <= 3 
+0

Эй спасибо за ваш ответ, я просто редактировал вопрос .. статусы заказа, будут храниться в базе данных с датой, это что-то вроде –

+0

Эй спасибо за ваш ответ, я просто редактировал вопрос .. статусы заказа будут храниться в базе данных по дате, это что-то вроде –

+0

Эй, спасибо за ваш ответ, я только что редактировал вопрос .. статусы заказа будут храниться в базе данных по дате, например, заказ № 1 был статус-заказ, созданный 18-го числа, а затем отправленный заказ на 19-й и поставленный 20-го числа –

3

Использование lag():

select o.* 
from (select o.*, 
      lag(o.status_date) over (partition by o.order_no order by o.status_date) as prev_sd, 
      lag(o.status) over (partition by o.order_no order by o.status_date) as prev_status 
     from orders o 
    ) o 
where prev_status = 2 and status = 3 and 
     (status_date - prev_sd) <= 3; 
+0

'order by' является обязательным в аналитическом предложении для' lag() '(как по очевидным логическим причинам, так и по правилам синтаксиса); без него запрос не будет компилироваться. – mathguy

+0

@mathguy. , , Благодарю. Я просто случайно оставил его. –

+0

Один маленький вопрос: если я хочу получить разницу между двумя другими статусами (например, статус 3 и 1), как мне это сделать? –

2

Аналитические функции (lag() в данном случае) позволяют избежать соединения и/или подзапросов, и может (и часто) намного быстрее.

with 
-- begin test data; not part of the solution 
    orders (order_no, status, status_date) as (
     select 1, 1, to_date('18-OCT-16', 'DD-MON-YY')from dual union all 
     select 1, 2, to_date('19-OCT-16', 'DD-MON-YY')from dual union all 
     select 1, 3, to_date('20-OCT-16', 'DD-MON-YY')from dual union all 
     select 1, 1, to_date('20-OCT-16', 'DD-MON-YY')from dual union all 
     select 1, 3, to_date('23-OCT-16', 'DD-MON-YY')from dual union all 
     select 1, 2, to_date('24-OCT-16', 'DD-MON-YY')from dual union all 
     select 1, 1, to_date('30-OCT-16', 'DD-MON-YY')from dual  
    ), 
-- end test data; solution is the word "with" from above, plus the query below  
    prep (order_no, status, status_date, prev_status, prev_status_date) as (
     select order_no, status, status_date, 
       lag(status) over (partition by order_no order by status_date), 
       lag(status_date) over (partition by order_no order by status_date) 
     from orders 
    ) 
select order_no 
from prep 
where status = 3 and prev_status = 2 and prev_status_date - status_date <= 3 
; 


ORDER_NO 
-------- 
     1