根据mysql

时间:2017-11-12 20:22:02

标签: php mysql

我有一个项目,主要的事务表和一些名为provider的子事务表。每个提供者都有自己的表。主表只保留金额(如子保持),日期和一些基本数据,也是子表的参考ID。我想基于 provider 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)
+-----+-----+-----+-----+----+--------+------+-----+

1 个答案:

答案 0 :(得分:1)

鉴于当前的表设计,获得所需结果的方法之一是将Transaction表“分解”为单独的查询,并将这些查询与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_providerp_providerA等进行更改时,新的p_providerB表格将会不同步。