簡體   English   中英

根據mysql中的值連接兩個以上的表

[英]Joining more than 2 tables based on value in mysql

我要處理一個項目,即主事務表和一些稱為提供程序的子事務表。 每個提供者都有自己的表。 主表只保留金額(子項也保留),日期和一些基本數據,以及子表的引用ID。 我想根據提供者 ID聯接子表。 如果事情變得混亂,我可以將表名保留為關聯數組。 讓我感到困惑的是,每個提供者的表都有不同的主鍵名稱。

提供程序表幾乎相同,除了一些列。 我真正想要實現的目標是在所有這三個表中執行搜索。

另一個問題是,這是否是一個愚蠢的想法,如果這樣的話,哪種方法會更好? 預計每天有400-500條記錄。 另請注意,將來可以添加更多的提供程序表。 這種結構是由比我更有經驗的人設計的,我無法相信任何人這是不好的。

Transaction
+-----+-----+-----+-----+
| id  | ref | prv | date|
+-----+-----+-----+-----+
| 1   | 4   | 2   | ..  |
+-----+-----+-----+-----+
| 2   | 4   | 3   | ..  |
+-----+-----+-----+-----+
| 3   | 5   | 2   | ..  |
+-----+-----+-----+-----+
| 4   | 7   | 1   | ..  |
+-----+-----+-----+-----+
| 5   | 22  | 3   | ..  |
+-----+-----+-----+-----+

Providers (prv value)
+-----+---------------+-----+
| pID | providerName  | ..  |
+-----+---------------+-----+
| 1   | providerA     | ..  |
+-----+---------------+-----+
| 2   | providerB     | ..  |
+-----+---------------+-----+
| 3   | providerC     | ..  |
+-----+---------------+-----+

p_providerA (ref value)
+-----+--------+------+-----+
| aID | amount | name | ..  |
+-----+--------+------+-----+
| 1   | 90.20  | alf  | ..  |
+-----+--------+------+-----+
| 2   | 70.00  |willie| ..  |
+-----+--------+------+-----+
| 3   | 43.10  | kate | ..  |
+-----+--------+------+-----+


p_providerB (ref value)
+-----+--------+------+-----+
| bID | amount | name | ..  |
+-----+--------+------+-----+
| 3   | 65.20  | jane | ..  |
+-----+--------+------+-----+
| 4   | 72.00  | al   | ..  |
+-----+--------+------+-----+
| 5   | 84.10  | bundy| ..  |
+-----+--------+------+-----+


p_providerC (ref value)
+-----+--------+------+-----+
| bID | amount | name | ..  |
+-----+--------+------+-----+
| 3   | 10.20  | mike | ..  |
+-----+--------+------+-----+
| 4   | 40.00  | kitt | ..  |
+-----+--------+------+-----+
| 6   | 27.60  | devon| ..  |
+-----+--------+------+-----+

預期結果

+-----+-----+-----+-----+----+--------+------+-----+
| id  | ref | prv | date|    |        |      |     |
+-----+-----+-----+-----+----+--------+------+-----+
| 1   | 4   | 2   | ..  | 4  | 72.00  | al   | ..  | (from prv. b)
+-----+-----+-----+-----+----+--------+------+-----+
| 2   | 4   | 3   | ..  | 4  | 40.00  | kitt | ..  | (from prv. c)
+-----+-----+-----+-----+----+--------+------+-----+

根據當前的表設計,獲得期望結果的一種方法是將“事務”表“分解”為單獨的查詢,然后將這些查詢與UNION ALL合並

Transaction表中的行可以這樣返回:

SELECT t.* FROM Transaction t WHERE t.prv = 1
 UNION ALL
SELECT t.* FROM Transaction t WHERE t.prv = 2 
 UNION ALL
SELECT t.* FROM Transaction t WHERE t.prv = 3
 UNION ALL 
...

現在,每個SELECT都可以實現對相應提供者表的聯接

SELECT t.*, pa.amount, pa.name
  FROM Transaction t 
  JOIN p_providerA pa ON pa.aid = t.ref
 WHERE t.prv = 1

 UNION ALL

SELECT t.*, pb.amount, pb.name
  FROM Transaction t
  JOIN p_providerB pb ON pb.bid = t.ref
 WHERE t.prv = 2 

 UNION ALL 

   ...

另一個選擇幾乎是丑陋的

SELECT t.*
     , CASE t.prv 
       WHEN 1 THEN pa.amount
       WHEN 2 THEN pb.amount
       WHEN 3 THEN pc.amount
       END AS `p_amount`
     , CASE t.prv 
       WHEN 1 THEN pa.name
       WHEN 2 THEN pb.name
       WHEN 3 THEN pc.name
       END AS `p_name`
  FROM Transaction t 
  LEFT JOIN p_providerA pa ON pa.aid = t.ref AND t.prv = 1
  LEFT JOIN p_providerB pb ON pb.bid = t.ref AND t.prv = 2
  LEFT JOIN p_providerC pc ON pc.cid = t.ref AND t.prv = 3

底線...無法在單個查詢中動態使用Providers表。 我們可以在預查詢中使用這些信息,以獲取一個有助於我們創建需要運行的語句的結果集。


另一個選擇(如果p_providerX表不是太大)將是在內聯視圖中將所有這些連接在一起,並連接到該視圖。 (這對於大型集合可能是昂貴的;派生表可能會在其上創建索引...)

 SELECT t.*
      , p.amount  AS p_amount
      , p.name    AS p_name  
   FROM `Transaction` t
   JOIN (
          SELECT 1 AS pID, pa.aid AS rID, pa.amount, pa.name FROM p_providerA
           UNION ALL
          SELECT 2       , pb.bid      , pb.amount, pb.name FROM p_providerB
           UNION ALL
          SELECT 3       , pc.cid      , pc.amount, pc.name FROM p_providerC
           UNION ALL
             ...
        ) p
    ON p.pID  = t.pID
   AND p.rID  = t.ref

如果我們要反復運行這樣的查詢,我們可以將內聯視圖具體化為表...我只是在這里猜測數據類型...

 CREATE TABLE p_provider
 ( pID      BIGINT UNSIGNED NOT NULL 
 , rID      BIGINT UNSIGNED NOT NULL
 , amount   DECIMAL(20,2)
 , name     VARCHAR(255)
 , PRIMARY KEY (pID,id) 
 );

 INSERT INTO p_provider (pID, rID, amount, name)
 SELECT 1 AS pID, pa.aid AS rID, pa.amount, pa.name FROM p_providerA
 ;
 INSERT INTO p_provider (pID, rID, amount, name)
 SELECT 2 AS pID, pb.aid AS rID, pb.amount, pb.name FROM p_providerB
 ;
 INSERT INTO p_provider (pID, rID, amount, name)
 SELECT 3 AS pID, pc.aid AS rID, pc.amount, pc.name FROM p_providerC
 ;
 ... 

然后引用新表

SELECT ...
 FROM `Transaction` t 
 JOIN `p_provider` p 
   ON p.piD = t.pID
  AND p.rID = t.ref

當然,當對p_providerAp_providerB等進行更改時,新的p_provider表將不同步。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM