2016-12-23 3 views
0

У меня есть два состояния пакета, то есть Dropped и Intransit, и оба состояния записываются в разные строки в базе данных, поэтому для Ex.sql разница времени между двумя состояниями

City1 Pkg1 Status Change_Date 
ABC 1234 Dropped 07-DEC-16 02.52.28.000000 PM 
ABC 1234 Intransit 07-DEC-16 05.52.28.000000 PM 

Итак, мне нужно, чтобы уровень города был средним из числа набранных минусов. Выпадало время для всего пакета. В этом примере для Pkg 1 разница составляет 3 часа, аналогично хочется получить на уровне города, что 1000 пакетов имеют разницу в среднем 2,8 часа.

+1

Какая СУБД вы используете? –

+0

Какой тип столбца 'Change_Date'? –

+0

Я использую Oracle DB –

ответ

-1

Вам нужно будет вложить запросы, и вы будете плохо работать на большом количестве пакетов, я думаю. Было бы легче иметь всю эту информацию в одном ряду так:

CityID PkgID Статус Intransit брошено

С вашей модели данных, я думаю, что один правильный синтаксис SQL будет что-то вроде (не проверено):

Select avg(time), city 
From (
    Select (b.dropped - c.transit) as time, a.city as city, a.packageId 
    From myTable a, 
     (Select d.Change_Date as dropped 
     From myTable d 
     where a.packageId = d.packageId and d.Status = 'Dropped') b, 
     (Select e.Change_Date as transit 
     From myTable e 
     where a.packageId = e.packageId and d.Status = 'Intransit') c 
) 
Group By city 
+1

Я считаю, что мы не можем сделать «b.dropped - b.transit», поскольку они не являются датой и только фиксированным статусом –

+0

Да, я понял, только что отредактировал – Piou

+0

Возможно, вам стоит проверьте его перед отправкой в ​​качестве ответа. Исправьте меня, если я неправильно понимаю, 'a',' b' и 'c' являются перекрестными соединениями ... – Prisoner

2

На самом деле вы должны сначала попытаться создать представление, которое сделает этот единственный объект таблицы, чтобы отобразить пакет в одной строке.

Учитывая структуру таблицы быть что-то вроде этого

 
CREATE TABLE `packageList` (
    `cityId` int(10) NOT NULL, 
    `packageId` int(10) NOT NULL, 
    `status` varchar(256) NOT NULL, 
    `changedate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

поэтому ваше мнение shoult быть создан на основе следующего запроса

 

    CREATE VIEW packageStatus AS 
    SELECT 
    pl1.cityId as cityId , 
    pl1.packageId as packageId , 
    pl1.changeDate as DropTIme, 
    pl2.changeDate as Picktime 
    FROM 
    `packageList` pl1 , `packageList` pl2 
    WHERE 
    pl1.status = "Droped" AND pl2.status = "Picked" 
    and pl1.packageId = pl2.packageId 

После этого он собирается быть простой запрос группы по на этой точке зрения только некоторые вещи, как ниже запроса

 

SELECT 
    tt.cityid,avg(DATEDIFF(tt.DropTIme,tt.Picktime)) 
FROM 
    (SELECT 
    pl1.cityId as cityId , 
    pl1.packageId as packageId , 
    pl1.changeDate as DropTIme, 
    pl2.changeDate as Picktime 
    FROM 
    `packageList` pl1 , `packageList` pl2 
    WHERE 
    pl1.status = "Droped" AND pl2.status = "Picked" 
    and pl1.packageId = pl2.packageId) as tmpTable tt Group BY cityId 

Ответ Использование только запроса с вне создавая вид будет Soome вещь, как следующим

 
SELECT 
    cityid,avg(DATEDIFF(DropTIme,Picktime))
FROM (SELECT pl1.cityId as cityId , pl1.packageId as packageId , pl1.changeDate as DropTIme, pl2.changeDate as Picktime FROM packageList pl1 , packageList pl2 WHERE pl1.status = "Droped" AND pl2.status = "Picked" and pl1.packageId = pl2.packageId) as tmpTable Group BY cityId

+0

, это, безусловно, самый элегантный и эффективный способ, хороший – Piou

+0

Спасибо за ответ, но нам не разрешено создавать таблицу, так что есть способ получить требуемый результат в формат таблицы, упомянутой ранее –

+0

, вы можете использовать временную таблицу в этом случае, это может быть немного медленным, но работать точно –

0

Просто вычесть CHANGE_DATE из предыдущего CHANGE_DATE:

select city, Pkg, status, Change_Date, 
     change_date - 
      lag(change_date, 1, change_date) over (partition by pkg order by case status when 'Dropped' then 1 else 2 end) as diff 
where status in ('Dropped', 'Intransit') 
from the_table; 

Результат вычитания одного date от другого является число, представляющее (дробные) дней между этими двумя значениями. Таким образом, 8 часов приведет к 0.33

The order by case status when 'Dropped' then 1 else 2 end сортирует строки со статусом Dropped перед теми, с различным статусом (предполагая, что есть только два значения)

Вы можете обернуть выше в производную таблицу, чтобы получить среднее продолжительность от этого:

select avg(diff) 
from (
    select city, Pkg, status, Change_Date, 
     change_date - 
      lag(change_date, 1, change_date) over (partition by pkg order by case status when 'Dropped' then 1 else 2 end) as diff 
    where status in ('Dropped', 'Intransit') 
    from the_table; 
) t; 
+0

У меня действительно есть запрос, связанный с ключевыми словами 'over' и' partition by', которые поддерживаются mysql ?? –

+0

@Anandthakkar: Нет, MySQL по-прежнему не поддерживает [современный SQL] (http://modern-sql.com/) (но вопрос никогда не был помечен 'mysql') –

+0

Правильный вопрос, похоже, связан с oracle, но мне было любопытно, в каком db он поддерживается, поскольку он кажется немного новым синтаксисом для mysql-разработчиков, поэтому подумал, чтобы спросить вас –

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