我正在编写一个带有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年之前”这样的值,但仍然保持可排序性。空字符串表示“未知”)
我正在尝试阅读有关一个人所有婚姻的相关数据,以便我可以使用复杂的比较来提供部分排序。例如,当一个人有两次婚姻,而我们不知道结婚日期时,如果配偶B的孩子在配偶B死后出生,我们可以推断出与配偶B的婚姻是先发生的。
对于每一次婚姻,我想要找回结婚日期,配偶的DOB,配偶的DOD和孩子的DOB。 (任何孩子;我只是用生日来抓住第一个物理记录。)这是一个有时有效的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的查询向导确定,因为对我来说最自然的连接顺序不起作用。
此查询似乎仅在至少有一个婚姻有子女出生日期时才有效。如果婚姻中没有一个孩子有出生日期,我会得到“此查询最多可以返回一个结果”的顺序错误。
有什么建议吗?
答案 0 :(得分:1)
关于错误
“此子查询最多可以返回一条记录。”
您的问题源于这样一个事实:如果TOP 1
存在“绑定”,则使用ACE / Jet(Access)数据库时,TOP 1
查询实际上可能会返回多行。例如,给出[People]数据......
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