2013-05-14 42 views
1

我正在用Access 2010後端和VB.NET前端編寫家族樹應用程序。 (長篇故事,在這裏不相關。) 大多數一切都可行,但我需要爲一個人排序婚姻。與排序家庭中的孩子一樣,我們不能只使用明顯的DateOfBirth或DateOfMarriage字段,因爲我們並不總是有值。這是我的數據結構的簡化快照當輔助表沒有記錄時SQL報告錯誤

People Table    Families Table 
- ID      - ID 
- FullName     - Husband 
- DOB (Date of Birth)  - Wife 
- DOD (Date of Death)  - DOM (Date of Marriage) 

PersonMarriage Table (a linking table) 
- Person (foreign key to People) 
- Family (foreign key to Families) 
- Spouse (foreign key to People) 
- Marriage Order (a contrived value to force the order we want) 

FamilyChild Table (a linking table) 
- Family (foreign key to Families) 
- Child (foreign key to People) 
- BirthOrder (a contrived value to force the order we want) 

(FWIW,我的出生日期,婚姻的日期是做作的,這樣我可以處理的值,如「1862年三月」和「1753年之前,」但仍保持sortability。空字符串表示「未知」)

我想讀取有關所有人的婚姻的相關數據,以便我可以使用複雜的比較來提供部分排序。例如,當一個人有兩次婚姻,而且我們不知道結婚日期時,如果配偶A的孩子在配偶B去世後出生,我們可以推斷與配偶B的婚姻是先發生的。

對於每次婚姻,我想檢索結婚日期,配偶的生日,配偶的國防部和小孩的生日。 (所有的孩子,我只是抓住了生日的第一個物理記錄。)下面是一個SQL查詢作品有時:

SELECT PersonMarriage.Family, PersonMarriage.Spouse, DOM, s.DOB, s.DOD, 
    (SELECT TOP 1 c.DOB FROM FamilyChild 
     LEFT JOIN People c ON FamilyChild.Child=c.ID 
    WHERE c.DOB<>"" AND FamilyChild.Family=PersonMarriage.Family) as ChildDOB 
FROM Families AS f INNER JOIN 
    (PersonMarriage INNER JOIN People AS s ON PersonMarriage.Spouse = s.ID) 
ON f.ID = PersonMarriage.Family 
WHERE PersonMarriage.Person=? 

請注意,我用的字段列表中的子查詢找到孩子。我確信我需要將子選擇子查詢移動到FROM子句並使用LEFT JOIN,但我只是沒有想到一個辦法。連接順序FWIW由Access的查詢嚮導確定,因爲對我來說看起來最自然的連接順序不起作用。

此查詢似乎只在至少有一個婚姻有一個出生日期的孩子時才起作用。當兩個婚姻都沒有生日的孩子時,我得到「此查詢最多隻能返回一個結果」的錯誤。

有什麼建議嗎?

回答

1

關於錯誤

「最多一個記錄可以通過這個子查詢返回。」

你的問題的事實,與ACE /射流(訪問)數據庫TOP 1查詢實際上可能返回多行,如果有一個「領帶」爲TOP 1莖。例如,給定[人物]資料...

ID FullName DOB   DOD 
-- -------- ---------- --- 
1 Dave  1967-07-01  
2 Gertrude 1968-03-21  
3 Alice  after 1968  
4 Duncan after 1987 
5 Ernest after 1987  
6 Richard after 2003  
7 Suzy  after 2003  

...查詢...

SELECT TOP 1 * FROM [People] ORDER BY [DOB] DESC 

...將返回兩行:

ID FullName DOB   DOD 
-- -------- ---------- --- 
7 Suzy  after 2003  
6 Richard after 2003 

所以,而不是子查詢...

(
    SELECT TOP 1 c.DOB 
    FROM FamilyChild LEFT JOIN People c 
      ON FamilyChild.Child=c.ID 
    WHERE c.DOB<>"" AND FamilyChild.Family=PersonMarriage.Family 
) as ChildDOB 

...嘗試使用

(
    SELECT MIN(c.DOB) 
    FROM FamilyChild LEFT JOIN People c 
      ON FamilyChild.Child=c.ID 
    WHERE c.DOB<>"" AND FamilyChild.Family=PersonMarriage.Family 
) as ChildDOB