1

以下に示すように、新しいレコードと更新されたレコードをすべて取得するには結合する必要がある 2 つの関連テーブルがあります。これらは、単純化されたテーブル構造を持つ代表的な例です。

最初のテーブルは項目のテーブルです。たとえば、すべての既存のメモと「新しい」メモおよび既存のメモの更新を含む「メモ」です。

2 番目のテーブルには、メモに対する保留中の変更/更新の詳細が含まれています。たとえば、メモが変更されている場合、その行は変更されて複製され、元のメモの ID、更新を含む行の ID、および更新を行ったユーザーを含む行が pendingUpdates テーブルに追加されます。新しいメモが追加された場合、元の 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 に答える