2017-01-27 14 views
2

私は望む結果を返すクエリを持っていますが、時間がかかります。誰もがこれを書く良い方法を知っていますか?グループごとに最新のデータを返すためのSQLクエリ。異なるグループごとにアクティブ/非アクティブ。

私はPrgno/Prgdateのグループごとに1つの行が必要です。 まず、最新のレコードを選択して各従業員のステータスを判断する必要があります。 それから、従業員がアクティブな場合、グループ全体がアクティブになります。

「A」レコードを選択するだけでは不十分です。特定の従業員の非アクティブレコードがアクティブレコードよりも最新である可能性があるからです。私は最初の3列(prgno、prgdate、従業員)によってグループ化された最新のレコードを選択し

SELECT X_Prgno,X_Prgdate,X_Status 
FROM (
    -- sq2 choose the 1st record when ordering by status, this will choose Active before Inactive 
    SELECT X_Prgno,X_Prgdate,X_Status, 
      ROW_NUMBER() OVER (PARTITION BY X_Prgno,X_Prgdate ORDER BY X_Status) AS rn 
    FROM (
     -- sq1 choose the most recently updated record per empno, prgno, prgdate 
     SELECT X_Empno,X_Prgno,X_Prgdate,X_Status, 
       X_Upddate AS Updated_datetime, 
       MAX(X_Upddate) OVER (PARTITION BY X_Empno,X_Prgno,X_Prgdate) AS Max_Updated_datetime 
     FROM X_demo 
     ) sq1 
    WHERE Updated_datetime = Max_Updated_datetime) sq2 
WHERE rn = 1 

:ここ

はクエリです。アクティブなレコードが存在する場合は、最初にアクティブなレコードを選択し、2つの列(prgno、prgdate)のみでグループ化します。

サンプル:(私はあなたがこのサンプルセットに上記のクエリを実行することができ、このことができます願っています)

create table X_demo(
X_Prgno char(6), 
X_Prgdate char(8), 
X_Empno int, 
X_Status char(1), 
X_Upddate datetime); 
insert into X_demo values ('P43','20170124',1033,'A','2015-07-06 23:05:32.000'); 
insert into X_demo values ('P43','20170124',1033,'I','2015-07-06 23:05:07.000'); 
insert into X_demo values ('P43','20170124',1033,'I','2015-07-06 23:03:58.000'); 
insert into X_demo values ('P43','20170124',1034,'A','2015-06-03 09:29:46.000'); 
insert into X_demo values ('P43','20170124',1029,'I','2015-06-03 07:26:36.000'); 
insert into X_demo values ('P43','20170124',1033,'I','2015-06-02 14:52:53.000'); 
insert into X_demo values ('P43','20170124',1010,'I','2015-06-02 14:52:12.000'); 
insert into X_demo values ('P43','20170124',1029,'I','2015-08-29 13:27:35.000'); 
insert into X_demo values ('P43','20170124',1074,'I','2015-05-19 01:20:06.000'); 

Prgno、Prgdate、およびEMPNOによって、私たちのグループでは、我々は6行が、最新返す必要がある場合は各従業員に対して 次に、PrgnoおよびPrgdateによって再グループ化して、このグループの「A」を返します。

希望する結果:任意の助け

X_Prgno X_Prgdate X_Status 
P43  20170124 A 

感謝。

2つの追加レコードを挿入し、2つのアクティブ従業員レコードの現在のレコードを非アクティブにすると、そのグループの結果は無効になります。

insert into X_demo values ('P43','20170124',1033,'I','2017-01-27 09:30:00.000'); 
insert into X_demo values ('P43','20170124',1034,'I','2017-01-27 09:30:00.000'); 

結果:

X_Prgno X_Prgdate X_Status 
P43  20170124 I 

がアップデート - 2017年1月30日

私は、ROW_NUMBER関数を使用して、サブクエリのPARTITION部分OVER MAXを変更しました。 クエリ実行時間が数秒改善されましたが、実行時間が長すぎます。

SELECT X_Prgno,X_Prgdate,X_Status 
FROM (
    -- sq2 choose the 1st record when ordering by status, this will choose Active before Inactive 
    SELECT X_Prgno,X_Prgdate,X_Status, 
      ROW_NUMBER() OVER (PARTITION BY X_Prgno,X_Prgdate ORDER BY X_Status) AS sq2_rn 
    FROM (
     -- sq1 choose the most recently updated record per prgno, prgdate, empno 
     SELECT X_Prgno,X_Prgdate,X_Empno,X_Status,X_upddate, 
       ROW_NUMBER() OVER (PARTITION BY X_Prgno,X_Prgdate,X_Empno 
         ORDER BY X_Upddate DESC,X_Status) AS sq1_rn 
     FROM X_demo) sq1 
    WHERE sq1_rn = 1) sq2 
WHERE sq2_rn = 1 
+0

ありがとうございました。 – NancyF

+0

グループごとに最新のアクティブレコードのみが必要ですか? –

+1

希望の結果を投稿してください。 – McNets

答えて

1

アクティブなレコードが優先されるdate/prgnoの従業員には、1つのレコードが必要です。

あなたがしたいことを理解することは、クエリを簡素化するのに役立ちます。

SELECT x.* 
FROM (SELECT x.*, 
      ROW_NUMBER() OVER (PARTITION BY X_Prgno, X_PrgDate 
           ORDER BY X_Upddate DESC, status 
           ) as seqnum 
     FROM X_demo x 
    ) x 
WHERE seqnum = 1; 

このクエリでは、(X_Prgno, X_PrgDate, status, X_Upddate)のインデックスがパフォーマンスに役立ちます。

+0

ほとんどですが、それほどではありません。私は従業員が最新のものを見つける必要がありますが、従業員がアクティブな場合、そのグループがアクティブになります。私が探している結果は、Prgno/Prgdateごとに1行です。 – NancyF

+0

インデックスとそのアプリケーションデータベースを追加できるかどうかがわかりますが、通常はそれらに触れません。 – NancyF

+0

@vkpとGordon - ありがとうございますが、解決策はまだありません。上記のクエリは1行を返しますが、すべてのテストケースで正しいとは限りません。すべての従業員の**最新の**レコードが非アクティブの場合、グループの結果は「非アクティブ」になります。従業員の最新のレコードがアクティブな場合、結果は「アクティブ」になります。間違っている場合、従業員1033および1034は、より最近の非アクティブの記録を有し、他の従業員はアクティブではないので、グループは非アクティブでなければならない。 @NancyF。 – NancyF

関連する問題