3

似ている列と異なる列を含む 2 つのテーブルがあります。異なる列を 1 つの結果セットにマージする結果を返す必要がありますが、いずれかのテーブルが一致しない可能性がある条件が必要です。ユニオンを試しましたが、NULL 値を持つ 2 つの行が返されました。一つだけお願いします。以下に 2 つのテーブルの例を示します。

TableA
----------------------------------------------------
| ID | ColumnA | ColumnB | ForeignKeyA | TimeStamp |
----------------------------------------------------
| 1  | Val1    | Val2    | KeyA        | 2013-01-01|
----------------------------------------------------
| 2  | Val3    | Val4    | KeyB        | 2013-01-02|
----------------------------------------------------

TableB
------------------------------------------
| ID | ColumnC | ForeignKeyA | TimeStamp |
------------------------------------------
| 1  | Val5    | KeyA        | 2013-01-01|
------------------------------------------
| 2  | Val6    | KeyC        | 2013-01-02|
------------------------------------------

そして、ここにいくつかの疑似クエリと私が望む戻り値があります:

1)

SELECT TableA.ColumnA AS ColumnA, 
TableA.ColumnB AS Column B, 
TableB.ColumnC  AS ColumnC,
TableA.id AS TableA_ID,
TableB.id AS TableB_ID
(WHERE ForeignKeyA in either table = KeyA and TimeStamp in either table = 2013-01-01)

>>
-------------------------------------------------------
| ColumnA | ColumnB | ColumnC | TableA_ID | TableB_ID |
-------------------------------------------------------
| Val1    | Val2    | Val5    | 1         | 1         |
-------------------------------------------------------

2)

SELECT TableA.ColumnA AS ColumnA, 
TableA.ColumnB AS Column B, 
TableB.ColumnC  AS ColumnC,
TableA.id AS TableA_ID,
TableB.id AS TableB_ID
(WHERE ForeignKeyA in either table = KeyB and TimeStamp in either table = 2013-01-02)

>>
 -------------------------------------------------------
| ColumnA | ColumnB | ColumnC | TableA_ID | TableB_ID |
-------------------------------------------------------
| Val3    | Val4    | Null    | 2         | Null      |
-------------------------------------------------------

3)

SELECT TableA.ColumnA AS ColumnA, 
TableA.ColumnB AS Column B, 
TableB.ColumnC  AS ColumnC,
TableA.id AS TableA_ID,
TableB.id AS TableB_ID
(WHERE ForeignKeyA in either table = KeyC and TimeStamp in either table = 2013-01-02)

>>
 -------------------------------------------------------
| ColumnA | ColumnB | ColumnC | TableA_ID | TableB_ID |
-------------------------------------------------------
| Null    | Null    | Val6    | Null      | 2         |
-------------------------------------------------------
4

2 に答える 2

1

ここでおそらくトリッキーな詳細は、通常のように参加するので(ForeignKeyA, TimeStamp)はなく、参加することです。ID

この簡略化された設定 (有効な列名を使用) では:

CREATE TABLE tbl_a (id int, col_a text, col_b text, fk_a text, ts timestamp);
INSERT INTO tbl_a VALUES
  (1, 'Val1', 'Val2', 'KeyA', '2013-01-01')
 ,(2, 'Val3', 'Val4', 'KeyB', '2013-01-02');

CREATE TABLE tbl_b (id int, col_c text,  fk_a text, ts timestamp);
INSERT INTO tbl_b VALUES
  (1, 'Val5', 'KeyA', '2013-01-01')
 ,(2, 'Val6', 'KeyC', '2013-01-02');

クエリは次のようになります。

SELECT a.col_a, a.col_b, b.col_c
      ,a.id AS a_id, b.id AS b_id
FROM   tbl_a a
FULL   JOIN tbl_b b USING (fk_a, ts)
WHERE  'KeyA' IN (a.fk_a, b.fk_a)
AND    '2013-01-01' IN (a.ts, b.ts);

CTE を使用するよりもかなり高速になるはずです。でテストしEXPLAIN ANALYZEます。

-> SQLfiddle デモ。

于 2013-09-30T23:56:44.537 に答える
1

クエリでは次のように使用できると思います(列を句にfull outer join追加できますが、何も変更されません):on

with
cteA as (select * from TableA where TimeStamp = _ts and ForeignKeyA = _fk),
cteB as (select * from TableB where TimeStamp = _ts and ForeignKeyA = _fk)
select
    A.ColumnA, A.ColumnB, B.ColumnC,
    A.ID as TableA_ID, B.ID as TableB_ID
from cteA as A
    full outer join cteB as B on 1 = 1

ただし、事前フィルタリングなしで使用できます(これは、インデックスと列full outer joinがある場合、効率が低下します):ForeignKeyATimeStamp

select
    A.ColumnA, A.ColumnB, B.ColumnC,
    A.ID as TableA_ID, B.ID as TableB_ID
from TableA as A
    full outer join TableB as B
        on B.ForeignKeyA = A.ForeignKeyA and B.TimeStamp = A.TimeStamp
where
    coalesce(A.ForeignKeyA, B.ForeignKeyA) = _fk and
    coalesce(A.TimeStamp, B.TimeStamp) = _ts

sql fiddle demo

于 2013-09-30T17:31:22.283 に答える