开发者

SQL Server/DB2: Same query returns different results?

Summary

I'm currently working on a project where I have to query against the underlying database engine for last changes of records that represents users accesses.

Each user may, and is not mandatory to, have children accounts. Children accounts are stored within the same data table with a reference to its parent through the ID_PUSR table field. When the account is a primary, ID_PUSR is null

Each time an acces is changed, a new record is then created in the database users table, with a last update date (DT_UPDT).


Data Sample

Please consider the following:

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_U开发者_开发技巧SER_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

I double-checked the data table content within both database servers and I can certify that they are identical records.


SQL/DB2 Query

This query is fully compatible with both SQL Server and DB2 database engines:

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

Different Results!

Despite the fact that I'm running the same exact identical query against the above-mentioned RDBMS, I obtain different results as follows:

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

These results appears to be good until we can see the difference between the two database engines. Notice the date values in the DT_UPDT field.

SQL Server

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

These results here in SQL Server are the one with which I shall come in DB2. They represent the "good" datum. As for the ID_USERS, they are just ID's, what matters are the dates.

Questions

  1. How can the same query returns different results using two SQL ANSI capable engines?
  2. Is it something with the datum which I don't seem to see?
  3. How is the WITH...AS () interpreted by DB2 that shall differ from SQL Server?

Nota Benne: A simple select * from USERS order by CD_USER reveals the same data.


Your query is undeterministic for ties.

row_number() over (partition by CD_USER order by CD_USER desc) as ROWNUM

doesn't define any particular row_numbering within each partition. If you want both RDBMS's to return the same results order by something unique so there are no ties and deterministic results.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜