Ingres

Visual DBA 中缺少的行,在專門查詢時存在

  • March 3, 2017

我有一個有趣的問題,Google讓我失望了。

背景

我正在處理使用 Ingres SQL 管理的醫療記錄。前幾天,我在 Excel 中編寫了一個簡單的查詢,以提取在設定日期範圍內死亡的所有患者行並將它們作為報告輸出。此查詢有效。我碰巧注意到(因為我的日期範圍)我錯過了最近的一行。經過進一步檢查,我意識到我遺漏了更多行,而不僅僅是在這份報告中。

問題詳情

當我專門查詢這些缺失的行(通過從其列中選擇其特定的患者 ID)時,它們存在。在它們所在的表中查看 Visual DBA 並且剛剛成功查詢時,它們不會出現。

同樣,這些缺失的行不會出現在我的 Excel 查詢提取的原始數據中,而符合相同條件的其他行會出現。我已經在 Visual DBA 中顯示的行與未顯示的行之間尋找不一致的地方。它們都是一致的(空值、格式等),並且僅在值而非類型上存在差異。即,姓氏是“瓊斯”而不是“史密斯”。

我的問題

為什麼 Ingres Visual DBA 中缺少行(假設是表“x”),但是當在 Ingres Visual SQL 中從表“x”中專門查詢時,它們會出現?

這對我們來說是一個嚴重的問題,因為自動生成的醫療報告中缺少行,並且可能會失去重要資訊。

額外細節

在 Visual DBA 的對像管理器中,我導航到有問題的表(例如d1_17,按 的升序排序d1_17.xpidxpid = '27245'不存在。當我在 Visual SQL 中專門查詢d1_17.xpid = '27245'它時,它會正確輸出該行。

它們連接到同一個數據庫。Excel 和 Visual DBA 也同步(都缺少相同的行)。當我d1_17.xpid = '27245'在 Visual SQL 中專門查詢並列印行時,就會出現差異,但是,在對像管理器中瀏覽時,d1_17在 Visual DBA 中,行xpid = '27245'不存在。

中的每個值d1_17.xpid都是非空的。其他列可能有空值,但每一行都是一個病人,每個病人都有一個xpid(病人 ID)。

雖然我們是數據庫的網路管理員,但很遺憾我們沒有創建它,但我們的 EHR GUI 軟體團隊也完成了這部分工作。

請原諒 SQL Server 測試案例 - 這個問題對於所有 SQL 實現來說都是常見的,因為 SQL 標準要求的通用語義。

即使您使用了 LEFT OUTER JOIN,如果您不正確地將常量測試條件放在 WHERE 子句而不是 JOIN 子句中,SQL 的語義也可以將其轉換為隱含的 INNER JOIN。下面的例子說明了這一點。

創建測試數據的準備工作:

if object_id('Address') is not null drop table Address;
if object_id('Person') is not null drop table Person;
create table Person (
   ID          int identity    not null primary key clustered,
   Name        varchar(10)     not null unique nonclustered
);

create table Address (
   ID          int identity    not null primary key clustered,
   PersonID    int             not null references Person(ID),
   SequenceNo  int             not null,
   Address     varchar(40)     not null

   ,constraint NK unique nonclustered (PersonID,SequenceNo)
);

insert Person(Name) values
    ('Fred')
   ,('George')
   ,('Ron')
   ,('Ginny')
;

with data as(
   select * from(values
           ('Ron',   1,'Attic bedroom, The Burrows')
          ,('Ron',   2,'Junior Boys Dorm, Gryffindor House')
          ,('Fred',  1,'Blue bedroom, The Burrows')
          ,('Fred',  2,'Senior Boys Dorm, Gryffindor House')
          ,('George',1,'Green bedroom, The Burrows')
          ,('George',2,'Senior Boys Dorm, Gryffindor House')
          ,('Ginny', 1,'Pink bedroom, The Burrows')
   )data(PersonName,SequenceNo,Address)
)
insert Address(PersonID,SequenceNo,Address)
select 
   Person.ID,
   SequenceNo,
   Address
from data join Person on data.PersonName = Person.Name
;

現在這兩個查詢

select *
from Person
left join Address on Address.PersonID = Person.ID
              where SequenceNo       = 2
;
select *
from Person
left join Address on Address.PersonID = Person.ID
                and SequenceNo       = 2
;

分別返回

ID          Name       ID          PersonID    SequenceNo  Address
----------- ---------- ----------- ----------- ----------- ----------------------------------------
3           Ron        2           3           2           Junior Boys Dorm, Gryffindor House
1           Fred       4           1           2           Senior Boys Dorm, Gryffindor House
2           George     6           2           2           Senior Boys Dorm, Gryffindor House

ID          Name       ID          PersonID    SequenceNo  Address
----------- ---------- ----------- ----------- ----------- ----------------------------------------
1           Fred       4           1           2           Senior Boys Dorm, Gryffindor House
2           George     6           2           2           Senior Boys Dorm, Gryffindor House
3           Ron        2           3           2           Junior Boys Dorm, Gryffindor House
4           Ginny      NULL        NULL        NULL        NULL

請注意,儘管希望確保返回所有Person行的 LEFT OUTER JOIN,但將條件放置SequenceNo = 2在 WHERE 子句而不是 JOIN 子句中如何將聯接強制為 INNER JOIN;以便從第一個結果集中刪除 Ginny。

這是一個具體的例子,更一般地說,在被測試的欄位中出現 NULL 值是如何違反直覺的。一個人失去了Excluded Middle,因此當謂詞A可能為 NULL 時,它不再是重言式的,A or NOT A它將為您提供所有行;A 的所有值為 NULL 的行都將被靜默刪除。

我懷疑日期值是問題所在。在 excel 中格式化日期時間值不會刪除時間部分,只會隱藏它。一個查詢正在截斷另一個不是的時間。如果您使用BETWEEN日期範圍,請在結束日期上添加 1 天並嘗試以下操作:

and Timestamp >= @StartDate and Timestamp < @EndDate

引用自:https://dba.stackexchange.com/questions/122488