2015-09-06 22 views
0

說我有表1:在1列中映射2列到2行?

stuff | sender_id | recipient_id 

,我有表2:

id | name 

我要回:

stuff | sender_name | recipient_name

stuff | sender_id | sender_name | recipient_id | recipient_name

現在我正在尋找像這樣的東西: SELECT * FROM table1 INNER JOIN table2 ON id=sender_id OR id=recipient_id但是,作爲一個行滿足兩個條件返回的東西duplicates。

有沒有辦法在1個查詢中獲取我想要的信息?

+0

對於那些RDBMS是這樣的?請添加相關標籤 - 謝謝 –

+1

由於您想從中獲得兩個不同的結果 –

回答

1

的方法是使用內選擇這樣的:

SELECT stuff, sender_id 
    , (SELECT name FROM table2 WHERE id = sender_id) AS sender_name 
    , recipient_id 
    , (SELECT name FROM table2 WHERE id = recipient_id) AS recipient_name 
FROM table1; 
0

而另一種方法是使用雙重加入。

SELECT 
     t1.stuff, 
     tA.id sender_id, 
     tA.name sender_name, 
     tB.id recipient_id, 
     tB.name recipient_name 
FROM 
    table1 t1 
inner join table2 tA 
    on t1.sender_id = tA.id 
inner join table2 tB 
    on t1.sender_id = tB.id 

將是有趣的使用explainanalyze

1

解決方案的一個參考表2比較兩種查詢:

select t1.stuff 
    , max(case when t1.sender_id = t2.id then t2.name end) as sender_name 
    , max(case when t1.recipient_id = t2.id then t2.name end) as recipint_name 
from t1 
join t2 
    on t2.id in (t1.sender_id, t1.recipient_id) 
group by t1.stuff; 

這是一個有點亂,但也有它就會得心應手情況。

我創建的表和與萬行,每行(DB2 Express-C中,10.5修訂包1)釀它們:

db2 "create table t1 (stuff int not null primary key, sender_id int not null, recipient_id int not null)" 
db2 "create table t2 (id int not null primary key, name varchar(10) not null); 
db2 "insert into t1 with t (n) as (values 0 union all select n+1 from t where n+1 < 10000) select n, 2*n, 2*n+1 from t" 
db2 "insert into t2 with t (n) as (values 0 union all select n+1 from t where n+1 < 10000) select 2*n, 'C' || rtrim(cast(2*n as char(10))) from t" 
db2 runstats on table t1 with distribution and sampled detailed indexes all 
db2 runstats on table t2 with distribution and sampled detailed indexes all 

並檢查不同的查詢計劃。我添加了一個WHERE子句

兩個子選擇:

db2 "explain plan for SELECT stuff    , (SELECT name FROM t2 WHERE id = sender_id) AS sender_name, (SELECT name FROM t2 WHERE id = recipient_id) AS recipient_name FROM t1 where t1.id between 500 and 600" 
db2exfmt -d sample -g -1 -o sub.exfmt 

兩個連接:

db2 "explain plan for SELECT t1.stuff, tA.name as sender_name, tB.name as recipient_name from t1 join t2 as tA on t1.sender_id = tA.id join t2 as tB on t1.sender_id = tB.id where t1.stuff between 500 and 600" 
db2exfmt -d sample -g -1 -o dualjoin.exfmt 

,最後用骨料和案例的變種:

db2 "explain plan for SELECT t1.stuff, max(case when t1.sender_id = t2.id then t2.name end) as sender_name, max(case when t1.recipient_id = t2.id then t2.name end) as recipint_name from t1 join t2 on t2.id in (t1.sender_id, t1.recipient_id) group by t1.stuff" 
db2exfmt -d sample -g -1 -o singlejoin.exfmt 

根據這一相當不科學的測試,@Juan Carlos Oropeza的解決方案是最便宜的:

Access Plan: 
----------- 
     Total Cost:    132.657 
     Query Degree:   1 

         Rows 
         RETURN 
         ( 1) 
         Cost 
         I/O 
         | 
         101.808 
         ^NLJOIN 
         ( 2) 
         132.657 
         53 
       /-------+--------\ 
      101.808     1 
      TBSCAN    FETCH 
      ( 3)    ( 7) 
      13.6735    13.6215 
       2     2 
       |    /---+----\ 
      101.808   1   10000 
      SORT   IXSCAN TABLE: LELLE 
      ( 4)   ( 8)   T2 
      13.6733  6.81423  Q1 
       2    1 
       |    | 
      101.808   10000 
      FETCH  INDEX: SYSIBM 
      ( 5) SQL150906110744470 
      13.6625   Q1 
       2 
      /---+----\ 
     101.808  10000 
     IXSCAN TABLE: LELLE 
     ( 6)   T1 
     6.84113  Q2 
      1 
     | 
     10000 
    INDEX: SYSIBM 
SQL150906110646160 
     Q2 

在@ shA.t使用兩個子選擇的更多的是有點貴:

Access Plan: 
----------- 
     Total Cost:    251.679 
     Query Degree:   1 

            Rows 
           RETURN 
           ( 1) 
            Cost 
            I/O 
            | 
           101.808 
           >^NLJOIN 
           ( 2) 
           251.679 
           103.99 
          /-------+--------\ 
         101.808     1 
         TBSCAN    FETCH 
         ( 3)    ( 12) 
         132.695    13.6215 
         52.9898     2 
         |    /---+----\ 
         101.808   1   10000 
         SORT   IXSCAN TABLE: LELLE 
         ( 4)   ( 13)   T2 
         132.691  6.81423  Q1 
         52.9898   1 
         |    | 
         101.808   10000 
         >^NLJOIN INDEX: SYSIBM 
         ( 5) SQL150906110744470 
         132.67   Q1 
         52.9898 
       /-------+--------\ 
      101.808     1 
      TBSCAN    FETCH 
      ( 6)    ( 10) 
      13.6881    13.6215 
       2     2 
       |    /---+----\ 
      101.808   1   10000 
      SORT   IXSCAN TABLE: LELLE 
      ( 7)   ( 11)   T2 
      13.6839  6.81423  Q2 
       2    1 
       |    | 
      101.808   10000 
      FETCH  INDEX: SYSIBM 
      ( 8) SQL150906110744470 
      13.6625   Q2 
       2 
      /---+----\ 
     101.808  10000 
     IXSCAN TABLE: LELLE 
     ( 9)   T1 
     6.84113  Q3 
      1 
     | 
     10000 
    INDEX: SYSIBM 
SQL150906110646160 
     Q3 

我的解決方案是最昂貴的一個:

Access Plan: 
----------- 
     Total Cost:    758.822 
     Query Degree:   1 

          Rows 
          RETURN 
          ( 1) 
          Cost 
          I/O 
          | 
          10000 
          GRPBY 
          ( 2) 
          758.139 
          124.996 
          | 
          20000 
          NLJOIN 
          ( 3) 
          756.923 
          124.996 
       /----------+----------\ 
       10000      2 
      FETCH      FETCH 
      ( 4)     ( 6) 
      122.351     27.0171 
       49      3.96667 
      /---+----\    /---+----\ 
     10000  10000   2   10000 
     IXSCAN TABLE: LELLE  RIDSCN TABLE: LELLE 
     ( 5)   T1   ( 7)   T2 
     58.1551  Q2   13.6291  Q1 
     21       2 
     |     /-------+-------\ 
     10000   1.0016    1.0016 
    INDEX: SYSIBM  SORT    SORT 
SQL150906110646160 ( 8)    ( 10) 
     Q2   6.81465    6.81465 
          1     1 
         |     | 
         1.0016    1.0016 
         IXSCAN    IXSCAN 
         ( 9)    ( 11) 
         6.81423    6.81423 
          1     1 
         |     | 
         10000    10000 
        INDEX: SYSIBM  INDEX: SYSIBM 
       SQL150906110744470 SQL150906110744470 
         Q1     Q1 
+0

雙內連接FTW,您將必須進行兩次連接。與測試很好的工作。 –