我有两个相关的表,如下所示,我需要加入以获取所有新的和更新的记录。这些是具有简化表结构的代表性示例。
第一个表是项目表,例如“注释”,它包含所有现有注释以及“新”注释和对现有注释的更新。
第二个表包含对笔记的未决更改/更新的详细信息。例如,如果一个便笺已被修改,则该行将被克隆并包含修改内容,并将一行添加到 pendingUpdates 表中,其中包含原始便笺的 id、具有更新的行的 id 以及进行更新的用户。如果添加了新注释,则工作流程类似,但原始 id 和修改后的 id 指的是同一行。
Notes:
+----+---------------------+----------------------------+
| id | title | text |
+----+---------------------+----------------------------+
| 1 | this is a test note | blah blah blah |
| 2 | note 2 | sdfsadfasdf |
| 3 | note 3 | jklhjklhjklhjk |
| 4 | note 3 | This is an update to note3 |
| 5 | note 3 | another update |
| 6 | note 4 | new note |
+----+---------------------+----------------------------+
pendingUpdates:
+----+------------+---------+------+
| id | originalId | cloneId | user |
+----+------------+---------+------+
| 1 | 3 | 4 | 1 |
| 2 | 3 | 5 | 1 |
| 3 | 6 | 6 | 2 |
+----+------------+---------+------+
我想做的是运行一个 SELECT 来获取所有注释,并包括该注释是否有更改(带有更新列表)和任何新注释。
因此,对于上面将返回第 1、2、3 和 6 行的示例。第 3 行也将 4,5 列为更新。
期望结果示例:
+----+------------+-------------+------+--------+---------------------+
| id | hasChanges | isNewRecord | p_id | clones | title |
+----+------------+-------------+------+--------+---------------------+
| 1 | no | no | NULL | NULL | this is a test note |
| 2 | no | no | NULL | NULL | note 2 |
| 3 | yes | no | 1 | 4,5 | note 3 |
| 6 | yes | yes | 3 | 6 | note 4 |
+----+------------+-------------+------+--------+---------------------+
我尝试了许多不同的查询组合,但还没有得到我所需要的。这是我得到的非常接近的结果,但是在结果集中包含了我不想要的第 4 行和第 5 行。
SELECT
o.id,
if(o.id = p.originalId, 'yes', 'no') AS hasChanges,
if(p.cloneId = p.originalId,
'yes',
'no') AS isNewRecord,
p.id AS p_id,
group_concat(p.cloneId
separator ',') AS clones,
o.title
FROM
`notes` AS o
LEFT JOIN
`pendingUpdates` AS p ON (o.id = p.originalId)
group by id;
这返回:
+----+------------+-------------+------+--------+---------------------+
| id | hasChanges | isNewRecord | p_id | clones | title |
+----+------------+-------------+------+--------+---------------------+
| 1 | no | no | NULL | NULL | this is a test note |
| 2 | no | no | NULL | NULL | note 2 |
| 3 | yes | no | 1 | 4,5 | note 3 |
->| 4 | no | no | NULL | NULL | note 3 |
->| 5 | no | no | NULL | NULL | note 3 |
| 6 | yes | yes | 3 | 6 | note 4 |
+----+------------+-------------+------+--------+---------------------+
解决方案:
这是我最终使用的最终解决方案,它与 fthiella 最相似。
再次感谢所有为此提供帮助的人。
SELECT
m.id,
if(m.max_pending IS NOT NULL, 'yes', 'no') hasChanges,
if(m.id = pendingUpdates.cloneId, 'yes', 'no') isNew,
m.clones,
m.pendingIds,
m.title
FROM (SELECT
Notes.id,
MAX(pendingUpdates.id) max_pending,
GROUP_CONCAT(pendingUpdates.id) pendingIds,
GROUP_CONCAT(pendingUpdates.cloneId) clones,
MAX(title) title
FROM Notes
LEFT JOIN pendingUpdates ON Notes.id = pendingUpdates.originalId
GROUP BY Notes.id
) m
LEFT JOIN pendingUpdates ON m.max_pending = pendingUpdates.id
WHERE
m.id NOT IN (SELECT
cloneId
FROM pendingUpdates
WHERE cloneId NOT IN (SELECT
originalId
FROM pendingUpdates)
)
order by id;