0

次のように、ゲームごとに異なるエントリを持つ「ゲーム」のテーブルがあります。

gameID   internalName
1        game1
2        game 1
3        game 2
4        game2
5        game3

したがって、問題は、ゲームのタイトル (空白を取り除いたもの) が同一であるケースを結合したいということです。別の例では、gameID が 2 の行は 1 とマージされ、削除されます。

さらに、gameID を外部キーとして使用している他のテーブルのエントリを更新して、新しいキーを指すようにしたいと考えています。

重複しているタイトルのリストを取得するために、次のようなことができることを知っています。

SELECT gameID, count(REPLACE(internalName, ' ', '')), internalName  FROM games GROUP BY REPLACE(internalName, ' ', '') HAVING count(REPLACE(internalName, ' ', ''))  > 1

しかし、それは私がしなければならないことを達成するのに本当に役立ちません。

何か助けはありますか?

4

1 に答える 1

2

そのような何かはあなたが始めるのを助けることができます

select g1.gameID as toKeep, g2.gameID toEliminate
from games g1
inner join games g2 on replace(g1.internalName, ' ', '') = replace(g2.internalName, ' ', '')
where g1.gameID < g2.gameID

しかし、マージするアイテムが 3 つある場合、これはうまく機能しません...

http://sqlfiddle.com/#!2/fb294/6を参照してください

しかし、ストアド プロシージャ内または php (または他の言語) では、それで必要なものを取得できるはずです。

より良い

これで、3つ、4つ、または5つの同一の結果でも機能します

select g1.gameID as toKeep, g2.gameID toEliminate
from games g1
inner join games g2 on replace(g1.internalName, ' ', '') = replace(g2.internalName, ' ', '')
where g1.gameID < g2.gameID
and g1.gameID not in (SELECT g4.gameID
                      from games g4
                      inner join games g3 on replace(g3.internalName, ' ', '') = replace(g4.internalName, ' ', '')
                      where g3.gameID < g4.gameID)

http://sqlfiddle.com/#!2/8fb21/1

EDIT : (テストされていない) ストアド プロシージャの例

CREATE PROCEDURE CLEANGAMENAMES()
BEGIN
  DECLARE toKeep, toEliminate INT;
  DECLARE cur1 CURSOR FOR 
    SELECT g1.gameID AS toKeep, g2.gameID AS toEliminate
    FROM games g1
    INNER JOIN games g2 ON REPLACE(g1.internalName, ' ', '') = REPLACE(g2.internalName, ' ', '')
    WHERE g1.gameID < g2.gameID
    AND g1.gameID NOT IN (SELECT g4.gameID
                          FROM games g4
                          INNER JOIN games g3 ON REPLACE(g3.internalName, ' ', '') = REPLACE(g4.internalName, ' ', '')
                          WHERE g3.gameID < g4.gameID)

  OPEN cur1;

  read_loop: LOOP
    FETCH cur1 INTO toKeep, toEliminate;
    UPDATE <anyTable> set gameId = toKeep where gameId = toEliminate;
    -- as many tables as you need
    DELETE FROM games where gameID = toEliminate;
    UPDATE games set internalName = REPLACE(internalName, ' ', '');

  END LOOP;

  CLOSE cur1;
END;
于 2012-05-24T22:16:06.083 に答える