0

一度に異なるテーブルのデータにアクセスしようとしていますが、別のテーブルの列の値を指定して、どのテーブルからデータを取得するかを決定できるようにしたいと考えています。

次に例を示します。

テーブル A: (id, table1_id, table1_type, table2_id, table2_type)

  • (1, 1, 'B_Type', 2, 'E_Type')
  • (2, 2, 'B_Type', 3, 'D_Type')
  • (3, 1, 'C_Type', 2, 'B_Type')

テーブル B: (id, some_values):

  • (1、「何か」)
  • (2、「その他」)

表 C、D、および E は B といくらか似ています。

だから、私は次のことをしたいと思います(疑似javascriptで行います):

result = db.Query("SELECT * from A WHERE [condition] LIMIT 1")
table1 = getTable(result.table1_type) // E.g. 'B' if 'B_Type'
table2 = getTable(result.table2_type)
new_results = db.Query("SELECT * from " + table1 + ", " + table2 + "  WHERE [condition]")

この方法は機能しますが、A の table_type 列に応じて条件付きでテーブルを選択する方法があることを期待していました。

どんな助けでも大歓迎です。

4

2 に答える 2

2

本当にこれを行いたい場合は、すべてのマルチ結合の中で最も醜いものが必要です。

SELECT
  IF(A.table1_type='B',B1.some_value,
    IF(A.table1_type='C',C1.some_value,
      IF(A.table1_type='D',D1.some_value,
        IF(A.table1_type='E',E1.some_value,
          NULL)))) AS table1_value,
  IF(A.table2_type='B',B2.some_value,
    IF(A.table2_type='C',C2.some_value,
      IF(A.table2_type='D',D2.some_value,
        IF(A.table2_type='E',E2.some_value,
          NULL)))) AS table2_value
FROM A
  LEFT JOIN B AS B1 ON A.table1_type='B' AND A.table1_id=B1.id
  LEFT JOIN C AS C1 ON A.table1_type='C' AND A.table1_id=C1.id
  LEFT JOIN D AS D1 ON A.table1_type='D' AND A.table1_id=D1.id
  LEFT JOIN E AS E1 ON A.table1_type='E' AND A.table1_id=E1.id
  LEFT JOIN B AS B2 ON A.table2_type='A' AND A.table2_id=B2.id
  LEFT JOIN C AS C2 ON A.table2_type='B' AND A.table2_id=C2.id
  LEFT JOIN D AS D2 ON A.table2_type='C' AND A.table2_id=D2.id
  LEFT JOIN E AS E2 ON A.table2_type='D' AND A.table2_id=E2.id
WHERE [condition for A];

編集

説明の言葉: MySQL (ほとんどの SQL データベースと同様) には、テーブルを動的に切り替える「意図した」方法がありません。これにより、すべてのテーブルを結合してから、1 つを除くすべての結果を削除する必要があります。ユースケースで 2 回繰り返します。

于 2013-10-23T22:09:31.977 に答える
0

大量の結合を避けたい場合は、カーソルと動的 SQL を使用してこれを達成できるはずです。

以下に例を示します (これは MSSQL 構文を使用して記述されていますが、MySql で同じでない場合は近いと思います):

CREATE TABLE #result
(table1Val varchar(50), table2Val varchar(50))

DECLARE @sql VARCHAR(MAX)

DECLARE @table1_val int, @table1_type varchar(50), @table2_val int, @table2_type varchar(50)
DECLARE cur CURSOR FOR
SELECT table1_id, table1_type, table2_id, table2_type
FROM A

OPEN cur
FETCH NEXT FROM Cur INTO @table1_val, @table1_type, @table2_val, @table2_type

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @sql = '
        INSERT INTO #result
        (SELECT val FROM ' +CASE @table1_type WHEN 'B_Type' THEN 'B' WHEN 'C_type' THEN 'C' + ' WHERE id = '''+@table1_val+'''),
        (SELECT val FROM ' +CASE @table2_type WHEN 'B_Type' THEN 'B' WHEN 'C_type' THEN 'C' + ' WHERE id = '''+@table2_val+''')
    '
    EXEC(@sql)
    --use this instead to debug the dynamic query
    --PRINT(@sql)
END
    UPDATE @JoinResult
    SET B_ID = SQ.ID,
        B_Age = SQ.AGE,
        B_Education = SQ.Education
    FROM (
        SELECT ID, AGE, EDUCATION
        FROM TableB b
        WHERE (
            abs((SELECT A_Age FROM @JoinResult WHERE A_Id = @i) - AGE) <=2
            AND abs((SELECT A_Education FROM @JoinResult WHERE A_Id = @i) - EDUCATION) <=2
        ) AND (SELECT B_ID FROM @JoinResults WHERE B_ID = b.id) IS NULL
    ) AS SQ 

CLOSE cur
DEALLOCATE cur
SELECT #result
DROP TABLE #result
于 2013-10-23T23:36:11.537 に答える