3

我有两个表,其中一些列相似,一些列不同。我需要返回一个将不同列合并到一个结果集中的结果,但是,我需要一个可能导致任何一个表都没有匹配项的条件,我尝试了一个联合,但它返回了两行具有空值的行,并且我想要一个。以下是两个示例表:

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

我认为在你的查询中你可以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 回答
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 回答