[英]How do I query a master-detail result having only the last detail row in MS-Access?
I have the following master table我有以下主表
.------------------.
| id | parent_name |
.------------------.
| 1 | Mike |
| 2 | Sarah |
| 3 | Danial |
| 4 | Alex |
.------------------.
And have the following child-table details:并具有以下子表详细信息:
.------------------------------------------.
| id | parent_id | child_name | birth year |
.------------------------------------------.
| 1 | 1 | mandy | 2000 |
| 2 | 1 | mark | 2003 |
| 3 | 1 | mathew | 2005 |
| 4 | 2 | sandy | 1998 |
| 5 | 2 | sharon | 2006 |
| 6 | 3 | david | 2001 |
.------------------------------------------.
In the example above, I delibretaly choose names of children with the first letter matching their parents' names just to make it easier to understand the relationship, even though each child is connected to his/her parent using the parent_id
.在上面的示例中,我故意选择第一个字母与父母姓名匹配的孩子的名字,以便更容易理解这种关系,即使每个孩子都使用
parent_id
连接到他/她的父母。
What I would like to have is a list of all parents (4 rows) and to have a matching 4 rows from the children table, selecting only the last born child of each respectful parent.我想要的是所有父母(4行)的列表,并从孩子表中匹配4行,只选择每个受人尊敬的父母的最后一个孩子。
.-------------------------------.
| id | parent_name | last_child |
.-------------------------------.
| 1 | Mike | mathew |
| 2 | Sarah | sharon |
| 3 | Danial | david |
| 4 | Alex | (null) |
.-------------------------------.
In oracle, this is easy:在 oracle 中,这很容易:
SELECT
p.id,
p.parent_name,
c.child_name last_child
FROM
parents_table p,
children_table c
WHERE
p.id = c.parent_id
AND c.birth_year = (SELECT MAX(birth_year) FROM children_table where parent_id = p.id)
But I am struggling to generate the same result in MS Access.. MS Access does not accept sub-queries (for select the child having the maximum birth year for the same parent).但是我正在努力在 MS Access 中生成相同的结果。MS Access 不接受子查询(对于 select,同一父母的最大出生年份的孩子)。
Is there a better way to get the result in MS Access?有没有更好的方法在 MS Access 中获得结果?
Access certainly does support subqueries, but you're using a crossjoin, so you will never get a null there. Access 确实支持子查询,但您使用的是交叉连接,因此您永远不会在那里获得 null。
Instead, left join and perform a subquery in the FROM
clause.相反,左连接并在
FROM
子句中执行子查询。 Your query would fail identically in Oracle, by the way.顺便说一句,您的查询在 Oracle 中同样会失败。 There are no relevant differences between Access and Oracle here.
Access 和 Oracle 之间没有相关差异。
SELECT
p.id,
p.parent_name,
c.child_name last_child
FROM
parents_table p
LEFT JOIN
(
SELECT *
FROM children_table c
WHERE c.birth_year = (SELECT MAX(c2.birth_year) FROM children_table c2 WHERE c2.parent_id = c.parent_id)
) c
ON p.id = c.parent_id
Access sometimes performs better with an EXISTS
, so a rewrite to that would be: Access 有时使用
EXISTS
表现更好,因此对其进行重写将是:
SELECT
p.id,
p.parent_name,
c.child_name last_child
FROM
parents_table p
LEFT JOIN
(
SELECT *
FROM children_table c
WHERE EXISTS(SELECT 1 FROM children_table c2 WHERE c2.parent_id = c.parent_id HAVING c.birth_year = MAX(c2.birth_year))
) c
ON p.id = c.parent_id
If you just want the child's name, you can use a correlated subquery:如果您只想要孩子的名字,您可以使用相关子查询:
select p.*,
(select top 1 child_name
from children_table as ct
where ct.parent_id = p.id
order by ct.birth_year desc, ct.child_name
) as youngest_child_name
from parents_table as p;
This can take advantage of an index on children_table(parent_id, birth_year desc, child_name)
.这可以利用
children_table(parent_id, birth_year desc, child_name)
上的索引。 With the index, I would expect this to be quite fast.有了索引,我希望这会很快。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.