3

概要:
詳細は以下を参照してください。[unanswered読みやすくするために、ここで多対多の質問をコピーしています。

    Given the "Input" table, what is the SQL to generate the 3rd "Output"
    table (Person_plays_Instrument)?



現在の入力 (1 テーブル):

OriginalTable:
PersonId PersonName Instrument_1 Instrument_2 Instrument_3 MailingAddress HomePhone
--------|----------|------------|------------|------------|--------------|------------
1        Bob        Violin       Viola        Trumpet      someplace      111-111-1111
2        Suzie      Cello        Flute        <null>       otherplace     222-222-2222
3        Jim        Violin       <null>       <null>       thirdplace     333-333-3333

望ましい出力 (3 つのテーブル):

Person:
Id Name   MailingAddress HomePhone
--|------|--------------|------------
1  Bob    someplace      111-111-1111
2  Suzie  otherplace     222-222-2222
3  Jim    thirdplace     333-333-3333

Instrument:
Id Name
--|-------
1  Violin
2  Cello
3  Viola
4  Flute
5  Trumpet

Person_plays_Instrument:
PersonId InstrumentId
--------|------------
1        1
1        3
1        5
2        2
2        4
3        1

詳細:

スプレッドシートとして始まった単一のフラット SQL テーブルがあります。正規化したい。これをテーブルごとに 1 つの質問に分割します。

質問 1 と 2 には回答がありましたが、他の人が役立つと思われる場合に備えて残しておきます。

質問:

質問 #1 : [answered]
Person テーブルを生成するにはどうすればよいですか?

回答 #1 :
この素晴らしい投稿により、2/3 の道のりを歩むことができます。1 対多のテーブルについては、準備ができています。コードは次のとおりです。

[add autonumber field to OriginalTable, name it PersonId]
[create empty Person table with Id, Name, MailingAddress, HomePhone fields]

INSERT INTO Person (Id, Name, MailingAddress, HomePhone)
  SELECT o.PersonID, o.PersonName, o.MailingAddress, o.HomePhone
  FROM OriginalTable as o
  WHERE o.PersonName Is Not Null;

質問#2[attempted](承認された回答の@Brankoによるより良いバージョン
Instrumentテーブルを生成するにはどうすればよいですか?

回答 #2 :
繰り返しますが、1 対多です。最初は、複数の列に困惑しました。
解決策は 2 つの部分に分かれていました。

  • 列ごとに 1 回、INSERT コマンドを繰り返すだけで済みます。
  • この投稿と IN 演算子を使用すると、その値をまだ挿入していないことを毎回確認できます。

コードは次のとおりです。

[create empty Instrument table with Id[autonumber], Name fields]

INSERT INTO Instrument (Name)
  SELECT Distinct o.Instrument_1
  FROM OriginalTable as o
  WHERE o.Instrument_1 Is Not Null
  AND o.Instrument_1 Not In (SELECT Name from Instrument);

INSERT INTO Instrument (Name)
  SELECT Distinct o.Instrument_2
  FROM OriginalTable as o
  WHERE o.Instrument_2 Is Not Null
  AND o.Instrument_2 Not In (SELECT Name from Instrument);

INSERT INTO Instrument (Name)
  SELECT Distinct o.Instrument_3
  FROM OriginalTable as o
  WHERE o.Instrument_3 Is Not Null
  AND o.Instrument_3 Not In (SELECT Name from Instrument);

質問 #3 : [unanswered]
Person_plays_Instrument テーブルを生成するにはどうすればよいですか?

4

1 に答える 1

4

OriginalTable.PersonIDあなたが私たちに示していないが、あなた自身の答え#1によって暗示されている があると仮定すると、答え#3は次のように簡単に表現できます。

INSERT INTO Person_plays_Instrument (PersonId, InstrumentId)
SELECT PersonID, Instrument.Id
FROM
    OriginalTable
    JOIN Instrument
        ON OriginalTable.Instrument_1 = Instrument.Name
        OR OriginalTable.Instrument_2 = Instrument.Name
        OR OriginalTable.Instrument_3 = Instrument.Name;

ところで、答え#2を表現するより簡潔な方法があります:

INSERT INTO Instrument (Name)
    SELECT *
    FROM (
        SELECT o.Instrument_1 I
        FROM OriginalTable as o
        UNION
        SELECT o.Instrument_2
        FROM OriginalTable as o
        UNION
        SELECT o.Instrument_3
        FROM OriginalTable as o
    ) Q
    WHERE I IS NOT NULL;

そして、これは完全に機能する MS SQL Server 用のSQL Fiddle の例です。他の DBMS も同様に動作するはずです。ところで、DBMS を示すために質問に適切なタグを付ける必要があります。

于 2013-02-07T11:40:24.797 に答える