1

我有两个相关的表,如下所示,我需要加入以获取所有新的和更新的记录。这些是具有简化表结构的代表性示例。

第一个表是项目表,例如“注释”,它包含所有现有注释以及“新”注释和对现有注释的更新。

第二个表包含对笔记的未决更改/更新的详细信息。例如,如果一个便笺已被修改,则该行将被克隆并包含修改内容,并将一行添加到 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;

http://sqlfiddle.com/#!2/8566e/1/0

4

2 回答 2

1

你可以找这个

   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)
where o.id in (select originalId from pendingUpdates)
or o.id in (select id from pendingUpdates)
group by id;

在这里演示

于 2013-04-08T22:20:31.990 回答
0

我已经以这种方式重写了您的查询(您的原始查询使用了一些非聚合列,并且在某些情况下这些列的值可能不确定):

SELECT
  m.id,
  CASE WHEN m.max_pending IS NOT NULL
       THEN 'yes' ELSE 'no' END hasChanges,
  CASE WHEN m.id=pendingUpdates.cloneId
       THEN 'yes' ELSE 'no' END isNew,
  m.min_pending pid,
  m.clones,
  m.title
FROM (
  SELECT
    Notes.id,
    MAX(pendingUpdates.id) max_pending,
    MIN(pendingUpdates.id) min_pending,
    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))

在此处查看小提琴。

于 2013-04-08T22:30:00.090 回答