概要
私は現在、ユーザーのアクセスを表すレコードの最後の変更について、基盤となるデータベースエンジンに対してクエリを実行する必要があるプロジェクトに取り組んでいます。
各ユーザーは、子アカウントを持つことができますが、必須ではありません。ID_PUSR
子アカウントは、テーブルフィールドを介した親への参照とともに、同じデータテーブル内に格納されます。アカウントがプライマリの場合、ID_PUSR is null
アクセスが変更されるたびに、データベースのユーザーテーブルに最終更新日(DT_UPDT
)を含む新しいレコードが作成されます。
データサンプル
次の点を考慮してください。
create table USERS (
ID_USERS INT // Primary key
, LN_USER VARCHAR(128)
, FN_USER VARCHAR(128)
, CD_USER VARCHAR(128)
, DT_UPDT DATETIME
, ID_PUSR INT // Foreign key to USERS.ID_USERS.
)
ID_USERS CD_USER LN_USER FN_USER DT_UPDT ID_PUSR
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
808 T_PEI00 LN_USER_00 FN_USER_00 2011-01-01-00.00.00.000000 NULL
809 T_PEI00 LN_USER_00 FN_USER_00 2010-01-01-00.00.00.000000 NULL
810 T_PEI00 LN_USER_00 FN_USER_00 2009-01-01-00.00.00.000000 NULL
811 T_PEI00 LN_USER_00 FN_USER_00 2008-01-01-00.00.00.000000 NULL
812 T_PEI00 LN_USER_00 FN_USER_00 2007-01-01-00.00.00.000000 NULL
813 T_PEI00A LN_USER_00 FN_USER_00 2011-01-01-00.00.00.000000 808
814 T_PEI00A LN_USER_00 FN_USER_00 2010-01-01-00.00.00.000000 809
815 T_PEI00A LN_USER_00 FN_USER_00 2009-01-01-00.00.00.000000 810
816 T_PEI00A LN_USER_00 FN_USER_00 2008-01-01-00.00.00.000000 811
817 T_PEI00A LN_USER_00 FN_USER_00 2007-01-01-00.00.00.000000 812
818 T_MAW00 LN_USER_01 FN_USER_01 2010-01-01-00.00.00.000000 NULL
819 T_MAW00 LN_USER_01 FN_USER_01 2009-01-01-00.00.00.000000 NULL
820 T_MAW00 LN_USER_01 FN_USER_01 2008-01-01-00.00.00.000000 NULL
821 T_MAW00 LN_USER_01 FN_USER_01 2007-01-01-00.00.00.000000 NULL
822 T_VEM08 LN_USER_08 FN_USER_08 2009-01-01-00.00.00.000000 NULL
823 T_VEM08 LN_USER_08 FN_USER_08 2008-01-01-00.00.00.000000 NULL
824 T_VEM08 LN_USER_08 FN_USER_08 2007-01-01-00.00.00.000000 NULL
825 T_LAC99 LN_USER_99 FN_USER_99 2008-01-01-00.00.00.000000 NULL
826 T_LAC99 LN_USER_99 FN_USER_99 2007-01-01-00.00.00.000000 NULL
両方のデータベースサーバー内のデータテーブルの内容を再確認し、それらが同一のレコードであることを証明できます。
SQL/DB2クエリ
このクエリは、SQLServerとDB2データベースエンジンの両方と完全に互換性があります。
with UPG as (
select ID_USERS
, CD_USER
, LN_USER
, FN_USER
, DT_UPDT
, ID_PUSR
, row_number() over (partition by CD_USER order by CD_USER desc) as ROWNUM
from USERS
) select ID_USERS
, CD_USER
, LN_USER
, FN_USER
, DT_UPDT
, ID_PUSR
, ROWNUM
from UPG
where ROWNUM = 1
order by CD_USER
異なる結果!
上記のRDBMSに対してまったく同じクエリを実行しているにもかかわらず、次のように異なる結果が得られます。
IBM DB2
ID_USERS CD_USER LN_USER FN_USER DT_UPDT ID_PUSR ROWNUM
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
826 T_LAC99 LN_USER_99 FN_USER_99 2007-01-01-00.00.00.000000 NULL 1
821 T_MAW00 LN_USER_01 FN_USER_01 2007-01-01-00.00.00.000000 NULL 1
808 T_PEI00 LN_USER_00 FN_USER_00 2011-01-01-00.00.00.000000 NULL 1
814 T_PEI00A LN_USER_00 FN_USER_00 2010-01-01-00.00.00.000000 809 1
822 T_VEM08 LN_USER_08 FN_USER_08 2009-01-01-00.00.00.000000 NULL 1
これらの結果は、2つのデータベースエンジンの違いがわかるまでは良好であるように見えます。DT_UPDT
フィールドの日付値に注意してください。
SQLサーバー
ID_USERS CD_USER LN_USER FN_USER DT_UPDT ID_PUSR ROWNUM
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
727 T_LAC99 LN_USER_99 FN_USER_99 2008-01-01 00:00:00.000 NULL 1
720 T_MAW00 LN_USER_01 FN_USER_01 2010-01-01 00:00:00.000 NULL 1
710 T_PEI00 LN_USER_00 FN_USER_00 2011-01-01 00:00:00.000 NULL 1
715 T_PEI00A LN_USER_00 FN_USER_00 2011-01-01 00:00:00.000 710 1
724 T_VEM08 LN_USER_08 FN_USER_08 2009-01-01 00:00:00.000 NULL 1
ここでのSQLServerでのこれらの結果は、DB2で使用する結果です。それらは「良い」基準を表します。はID_USERS
IDだけで、重要なのは日付です。
質問
- 2つのSQLANSI対応エンジンを使用して、同じクエリで異なる結果を返すにはどうすればよいですか?
- 見えないデータムのあるものですか?
WITH...AS ()
SQL Serverとは異なるDB2による解釈はどうですか?
Nota Benne:単純なselect * from USERS order by CD_USER
ものは同じデータを明らかにします。