一对多关联表SQL查询问题:获取主表ID、子表最后Evento与首次DataInserimento
问题排查与解决方案
现有一对多关联的主表Subattivita和子表Eventi(关联字段为Subattivita.ID与Eventi.IDSubattivita),需要查询主表ID、子表对应最后一条记录的Evento值,以及子表首次的DataInserimento值。执行自行编写的SQL时,Access提示需输入u.Evento的值,无法得到预期结果,现排查错误并提供正确方案。
表结构与示例数据
主表Subattivita
| ID | Contenuto |
|---|---|
| 1 | 测试 |
| 2 | 测试2 |
| 3 | 测试3 |
| 4 | 测试4 |
| 5 | 测试5 |
| 6 | 测试6 |
| 7 | 测试7 |
| 9 | 绘制图纸 |
| 10 | 测试8 |
子表Eventi
| ID | IDSubattivita | Evento | Commento | DataInserimento |
|---|---|---|---|---|
| 1 | 1 | Aperta | 自动插入 | 01/08/2024 |
| 2 | 2 | Aperta | 自动插入 | 01/08/2024 |
| 3 | 3 | Aperta | 自动插入 | 01/08/2024 |
| 4 | 4 | Aperta | 自动插入 | 01/08/2024 |
| 5 | 5 | Aperta | 自动插入 | 02/08/2024 |
| 8 | 6 | Aperta | 自动插入 | 02/08/2024 |
| 9 | 7 | Aperta | 自动插入 | 02/08/2024 |
| 12 | 9 | Aperta | 自动插入 | 02/08/2024 |
| 13 | 10 | Aperta | 自动插入 | 02/08/2024 |
| 14 | 1 | Remarks | Testo1 | 05/08/2024 |
| 15 | 2 | Remarks | Testo2 | 05/08/2024 |
| 16 | 3 | Remarks | Testo3 | 06/08/2024 |
| 17 | 4 | Remarks | Testo4 | 06/08/2024 |
| 18 | 5 | Remarks | Testo5 | 07/08/2024 |
| 19 | 6 | Remarks | Testo8 | 08/08/2024 |
| 20 | 7 | Remarks | Testo9 | 09/08/2024 |
| 21 | 9 | Remarks | Testo12 | 09/08/2024 |
| 22 | 9 | Remarks | 继续绘制图纸。 | 09/08/2024 |
| 23 | 9 | Caricata | 图纸已上传。 | 09/08/2024 |
| 24 | 9 | Chiusa | 图纸已批准 | 09/08/2024 |
期望查询结果
| ID | LastEvento | FirstDataInserimento |
|---|---|---|
| 1 | Remarks | 01/08/2024 |
| 2 | Remarks | 01/08/2024 |
| 3 | Remarks | 01/08/2024 |
| 4 | Remarks | 01/08/2024 |
| 5 | Remarks | 02/08/2024 |
| 6 | Remarks | 02/08/2024 |
| 7 | Remarks | 02/08/2024 |
| 9 | Chiusa | 02/08/2024 |
| 10 | Aperta | 02/08/2024 |
尝试的SQL语句
SELECT t.ID, u.Evento as LastEvento, p.DataInserimento as FirstDataInserimento FROM ((Subattivita t INNER JOIN (SELECT IDSubattivita, MAX(ID) as MaxID FROM Eventi GROUP BY IDSubattivita) u ON t.ID = u.IDSubattivita) INNER JOIN (SELECT IDSubattivita, MIN(ID) as MinID FROM Eventi GROUP BY IDSubattivita) p ON t.ID = p.IDSubattivita);
错误原因分析
子查询u仅返回IDSubattivita和MaxID两个字段,并未包含Evento字段,因此Access会将u.Evento识别为未定义参数,弹出输入框要求赋值。同理,子查询p也只返回IDSubattivita和MinID,缺少DataInserimento字段,这也是导致异常的原因之一。
正确的查询方案
需要将子查询得到的最大/最小ID,再次关联回Eventi表,获取对应的Evento和DataInserimento值。以下是适配Access的SQL语句:
SELECT t.ID, last_event.Evento AS LastEvento, first_data.DataInserimento AS FirstDataInserimento FROM Subattivita t LEFT JOIN ( SELECT e1.IDSubattivita, e1.Evento FROM Eventi e1 INNER JOIN (SELECT IDSubattivita, MAX(ID) AS MaxID FROM Eventi GROUP BY IDSubattivita) e2 ON e1.ID = e2.MaxID ) last_event ON t.ID = last_event.IDSubattivita LEFT JOIN ( SELECT e1.IDSubattivita, e1.DataInserimento FROM Eventi e1 INNER JOIN (SELECT IDSubattivita, MIN(ID) AS MinID FROM Eventi GROUP BY IDSubattivita) e2 ON e1.ID = e2.MinID ) first_data ON t.ID = first_data.IDSubattivita WHERE last_event.IDSubattivita IS NOT NULL OR first_data.IDSubattivita IS NOT NULL;
说明
- 使用
LEFT JOIN可确保即使主表无对应子表记录时也能返回结果(若不需要此类记录,可改为INNER JOIN) - 子查询
last_event通过最大ID关联Eventi表,获取每个IDSubattivita对应的最后一条Evento值 - 子查询
first_data通过最小ID关联Eventi表,获取每个IDSubattivita对应的首次DataInserimento值 WHERE子句用于过滤无任何子表记录的主表行(若需保留这类行,可删除该条件)
内容的提问来源于stack exchange,提问作者Luca
相关产品推荐
相关产品推荐

