0

重複したレコードでデータベースをクリーンアップしようとしています。参照を単一のレコードに移動し、他のレコードを削除する必要があります。

プロモーターと会場の 2 つのテーブルがあり、それぞれに都市というテーブルへの参照があります。問題は、同じ名前で異なる ID を持つ都市が存在し、会場やプロモーターと関係があることです。

このクエリを使用すると、すべてのプロモーターと会場を 1 つの都市レコードでグループ化できます。

SELECT c.id as id, c.name as name, GROUP_CONCAT( DISTINCT p.id ) as promoters_ids, GROUP_CONCAT( DISTINCT v.id ) as venues_ids
FROM cities as c
LEFT JOIN promoters as p ON p.city_id = c.id
LEFT JOIN venues as v ON v.city_id = c.id
WHERE c.name IN ( SELECT name from cities group by name having count(cities.name) > 1 )
GROUP BY c.name

ここで、プロモーターに対して UPDATE クエリを実行し、city_id を上記のクエリの結果と等しくなるように設定します。

このようなもの:

    UPDATE promoters AS pr SET pr.city_id = (
        SELECT ID
        FROM (
            SELECT c.id as id, c.name as name, GROUP_CONCAT( DISTINCT p.id ) as promoters_ids
            FROM cities as c
            LEFT JOIN promoters as p ON p.city_id = c.id

            WHERE c.name IN ( SELECT name from cities group by name having count(cities.name) > 1 ) AND pr.id IN promoters_ids
            GROUP BY c.name
            ) AS T1 

    )

これどうやってするの?

ありがとう

4

1 に答える 1

3

私の理解が正しければ、重複した都市を (最終的に) 削除したいので、そのプロセスで削除したい都市のいずれかにリンクされているプロモーターを更新する必要があります。

同じ名前の都市の最小の ID を使用することは理にかなっていると思います (最大の ID を使用することもできますが、少なくとも指定したいので、私に任せないでください。

したがって、プロモーターの正しい ID を取得するには、次のことを行う必要があります。 既にプロモーターにリンクされている都市と同じ名前を持つすべての都市の中で最も小さい ID を選択します。

幸いなことに、その要求は次のクエリにぴったりとはまります。

UPDATE promoters AS pr 
SET pr.city_id = (
  SELECT 
    -- Select the lowest ID ..
    Min(c.id)
  FROM
    -- .. of all cities ..
    Cities c
    -- .. that have the same name ..
    INNER JOIN Cities pc on pc.Name = c.Name
  WHERE
    .. as the city already linked to the promoter being updated
    pc.id = pr.city_id
  GROUP BY
    c.name)

秘訣は、Cities 自体を名前で結合することです。これにより、同じ名前のすべての都市を簡単に取得できます。句で同じことを試みたと思いますが、INそれは必要以上に複雑です。

group_concatすでに名前でグループ化しているので意味がありませんが、埋め込まれたクエリが実際に正しい都市を返すかどうかを確認する以外に、まったく必要ないと思います。このように書くと、これがうまくいかないはずがないことがわかります。

  SELECT 
    -- Select the lowest ID ..
    MIN(c.id) AS id,
    GROUP_CONCAT(c.name) AS names --< already grouped by this, so why...
  FROM
    -- .. of all cities ..
    Cities c
    -- .. that have the same name.
    INNER JOIN Cities pc on pc.Name = c.Name
  GROUP BY
    c.name

質問を正しく理解できたと思います。

于 2013-08-08T07:56:33.967 に答える