1

我正在编写一个带有 Access 2010 后端和 VB.NET 前端的 Family Tree 应用程序。(长篇大论,与此无关。)大多数事情都有效,但我需要为一个人整理婚姻。与对家庭中的孩子进行排序一样,我们不能只使用明显的 DateOfBirth 或 DateOfMarriage 字段,因为我们并不总是有值。这是我的数据结构的简化快照

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 年 3 月”和“1753 年之前”这样的值,但仍然保持可排序性。空字符串表示“未知”)

我正在尝试阅读有关一个人所有婚姻的相关数据,以便我可以使用复杂的比较来提供部分排序。例如,当一个人有两次婚姻,并且我们不知道结婚日期,如果配偶 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 的查询向导确定,因为对我来说最自然的连接顺序不起作用。

此查询似乎仅在至少有一个婚姻中有一个孩子的出生日期时才有效。当两个婚姻都没有出生日期的孩子时,我收到“此查询最多返回一个结果”的顺序错误。

有什么建议么?

4

1 回答 1

1

Regarding the error

"At most one record can be returned by this subquery."

Your problem stems from the fact that with an ACE/Jet (Access) database a TOP 1 query may actually return more than one row if there is a "tie" for TOP 1. For example given the [People] data...

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     

...the query...

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

...will return two rows:

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

So, instead of the subquery...

(
    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

...try using

(
    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
于 2013-05-15T08:46:52.727 回答