【问题标题】:SQL Server/DB2: Same query returns different results?SQL Server/DB2:相同的查询返回不同的结果?
【发布时间】:2011-06-24 13:04:03
【问题描述】:

总结

我目前正在从事一个项目,我必须针对底层数据库引擎查询代表用户访问的记录的最后更改。

每个用户都可以拥有儿童帐户,但并非强制要求。子帐户存储在同一数据表中,并通过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 查询

此查询与 SQL Server 和 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

在我们看到两个数据库引擎之间的差异之前,这些结果似乎很好。注意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

SQL Server 中的这些结果是我将在 DB2 中使用的结果。它们代表“好”数据。至于ID_USERS,它们只是ID,重要的是日期。

问题

  1. 同一查询如何使用两个支持 SQL ANSI 的引擎返回不同的结果?
  2. 是不是我似乎看不到的数据?
  3. WITH...AS () 如何被 DB2 解释为与 SQL Server 不同?

Nota Benne:一个简单的select * from USERS order by CD_USER 揭示了相同的数据。

【问题讨论】:

  • 愚蠢的问题:DB2 是否从 1 开始对行进行编号?还是为零?
  • 另外,不应该只是:,row_number() over (order by CD_UTILT_GIA desc) as ROWNUM
  • 检查后,DB2 从 1 开始编号。感谢您的提问,这可能是一个合理的问题。
  • row_number() over (partition by CD_USER order by CD_USER) as ROWNUM 允许我选择ROWNUM = 1,因为它在CD_USER 更改时重置,我需要选择我感兴趣的数据,否则ROWNUM 计算字段只是 ID_USERS 上的一个虚拟增量值,我没有特别使用它,除非我的查询有误。
  • @Will - 您的查询对于关系是不确定的。

标签: sql-server-2005 db2 resultset with-statement


【解决方案1】:

您的查询对于关系不确定。

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

没有在每个分区中定义任何特定的 row_numbering。如果您希望两个 RDBMS 按唯一的顺序返回相同的结果顺序,那么就没有联系和确定性结果。

【讨论】:

  • +1 并接受了答案!非常感谢!我不习惯使用ROW_NUMBER() 之类的东西,所以我欠你一个!最诚挚的感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-29
  • 1970-01-01
  • 2019-06-25
  • 2014-09-24
相关资源
最近更新 更多