2016-12-23 7 views
0

私はパッケージの2つのステータス、すなわちDroppedとIntransitを持っており、両方のステータスがデータベースの異なる行に取り込まれています。sqlの2つのステータス間の時間の差

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

どのDBMSを使用していますか? –

+0

'Change_Date'とは何ですか? –

+0

私はOracle DBを使用しています –

答えて

-1

リクエストをネストする必要があり、大量のパッケージではパフォーマンスが低下します。そのように一列にこのすべての情報を持っていることが容易されているでしょう:

CityID pkgidはステータスIntransitは、あなたのデータモデルで

をドロップ私は1つの正しい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

まず最初に、この単一のテーブルエンティティにパッケージを1行で表示させるビューを作成してください。

考慮すると、テーブルの構造は、ので、あなたのビューがそのビュー上でその後のクエリ次

 

    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 

グループの単純なクエリであることを行っているに基づいて作成されshoultこの

 
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; 

ようなものになります以下のクエリのようなもののみ

 

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 

回答クエリのみを使用する

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を減算した結果が(分数)の日を表す数である:outは

 
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

この場合、tempraroryテーブルを使用すると少し遅くなる可能性がありますが、確かに動作します –

0

を次のように直前CHANGE_DATEからCHANGE_DATEを引くようなビューはsoomeものであろう作成とこれらの2つの値の間。だから、8時間は0.33

order by case status when 'Dropped' then 1 else 2 endにつながる(2つだけの値があると仮定すると)異なる状況とそれらの前の状態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

私は実際にmysqlでサポートされているキーワード 'over'と' partition by'に関連するクエリを持っていますか? –

+0

@Anandthakkar:いいえ、MySQLはまだ[現代のSQL](http://modern-sql.com/)をサポートしていません(ただし、質問にはmysqlというタグは付いていません)。 –

+0

実際に質問は関連しているようですオラクルのみですが、MySQLのサポート窓関数を除いて、本質的にすべての現代DBMS –

関連する問題