【问题标题】:Pivot from 3 Tables with Dynamic Value从 3 个具有动态值的表中透视
【发布时间】:2020-08-04 08:30:09
【问题描述】:

我想使用下表创建一个数据透视表,但在此之前这是我的表

tbl_branch

tbl_product

tbl_orders

现在。它们都是动态的,意味着很快我将添加新的分支,新的项目,订单将继续。现在这是我想要实现的输出。

如何添加每个分支和项目的总数量?基本上它是一个数据透视表。如果是静态的就好了,但是3张表会不断的添加数据。

【问题讨论】:

  • 仅存储过程...
  • @Akina 是的,这就是我真正的想法,但我不知道如何做到:(
  • @NardongBagsik 你开始研究支点了吗?你试过什么吗?现在,看起来你已经放弃了你的要求,并希望有人会绝望地获得独角兽积分来免费完成你的工作。请尽你所能减轻志愿者的负担——作为对他们免费服务的尊重。
  • @mickmackusa 我怎样才能减轻它?到目前为止,我实现的是仅按行显示输出:( 很难测试这个
  • Akina 在 SO(和 IIRC,编写了某种枢轴库或其他东西)上处理了许多枢轴问题,并且值得信赖。 Aso,Bill Karwin 和 Rick James 几乎没有什么是 sql 做不到的。 stackoverflow.com/a/8977988/2943403

标签: php mysql pivot-table


【解决方案1】:

一个示例数据透视表查询如下所示:

select p.description as item,
  sum(case o.branch_id when 1 then o.qty else 0 end) as `Branch 1`,
  sum(case o.branch_id when 2 then o.qty else 0 end) as `Branch 2`,
  sum(case o.branch_id when 3 then o.qty else 0 end) as `Branch 3`,
  sum(case o.branch_id when 4 then o.qty else 0 end) as `Branch 4`,
  sum(case o.branch_id when 5 then o.qty else 0 end) as `Branch 5`,
  sum(case o.branch_id when 6 then o.qty else 0 end) as `Branch 6`,
  sum(o.qty) as `Total Qty`
from tbl_product as p
join tbl_orders as o on p.id = o.item_id
join tbl_branch as b on o.branch_id = b.id
group by p.id;

输出:

+-----------+----------+----------+----------+----------+----------+----------+-----------+
| item      | Branch 1 | Branch 2 | Branch 3 | Branch 4 | Branch 5 | Branch 6 | Total Qty |
+-----------+----------+----------+----------+----------+----------+----------+-----------+
| Product 1 |       12 |        0 |       67 |        1 |        0 |        0 |        80 |
| Product 2 |        3 |        0 |        0 |        0 |        1 |        0 |         4 |
| Product 3 |        1 |        4 |        0 |        0 |        0 |        0 |         5 |
| Product 4 |        2 |        0 |        5 |        0 |        0 |        0 |         7 |
| Product 5 |        0 |        0 |        0 |        0 |        0 |        3 |         3 |
+-----------+----------+----------+----------+----------+----------+----------+-----------+

您问如何使这种“动态化”,因为您会定期获得新产品和新分支。

SQL 要求选择列表的所有列在解析查询时都是固定的。在检查数据时,您不能根据在执行期间发现的不同值的数量来动态扩展其列列表的任何 SQL 查询。

尝试根据查询结果扩展其选择列表的查询就像编写一个 PHP 函数,其参数数量取决于函数的返回值!换句话说,这是一个先有鸡还是先有蛋的问题。您必须在调用之前定义函数,并且函数的定义取决于该函数返回的结果。这毫无意义。

因此,所有数据透视表样式的查询都必须在两个单独的 SQL 查询中完成:

  1. 获取要转换为列的不同值的列表。例如:

     select id, branch_name from tbl_branch;
    
  2. 将第一个查询的结果格式化为数据透视表查询的选择列表,就像我之前展示的那样。

如果您不想运行两个 SQL 查询,另一种方法是在 SQL 中进行数据透视。只需获取数据库中存在的行,然后编写代码以将结果“透视”为您喜欢的表格演示文稿。

【讨论】:

    【解决方案2】:

    您可以进行动态查询,因为您永远不知道将来会拥有哪些分支和产品

    架构 (MySQL v8.0)

    CREATE TABLE tbl_branch (
      `ID` INTEGER,
      `Branch_Name` VARCHAR(8)
    );
    
    INSERT INTO tbl_branch
      (`ID`, `Branch_Name`)
    VALUES
      ('1', 'Branch 1'),
      ('2', 'Branch 2'),
      ('3', 'Branch3'),
      ('4', 'Branch4'),
      ('5', 'Branch5'),
      ('6', 'Branch 6');
      
    
    CREATE TABLE tbl_product (
      `ID` INTEGER,
      `Description` VARCHAR(10)
    );
    
    INSERT INTO tbl_product
      (`ID`, `Description`)
    VALUES
      ('1', 'Product 1'),
      ('2', 'Product2'),
      ('3', 'Product 3'),
      ('4', 'Product 4'),
      ('5', 'Product 5'),
      ('6', 'Product 6'),
      ('7', 'Product 7'),
      ('8', 'Product 8'),
      ('9', 'Product 9'),
      ('10', 'Product 10');
    
    CREATE TABLE tbl_orders (
      `ID` INTEGER,
      `Branch_ID` INTEGER,
      `Item_ID` INTEGER,
      `Qty` INTEGER
    );
    
    INSERT INTO tbl_orders
      (`ID`, `Branch_ID`, `Item_ID`, `Qty`)
    VALUES
      ('1', '1', '1', '12'),
      ('2', '1', '2', '3'),
      ('3', '2', '3', '4'),
      ('4', '3', '4', '5'),
      ('5', '3', '1', '67'),
      ('6', '4', '1', '1'),
      ('7', '5', '2', '1'),
      ('8', '1', '3', '1'),
      ('9', '1', '4', '2'),
      ('10', '6', '5', '3');
    

    查询 #1

    SELECT 
      GROUP_CONCAT(DISTINCT
        CONCAT(
          'SUM(CASE o.`Branch_ID` WHEN "',
         o.`Branch_ID`,
          '" THEN o.`Qty` ELSE 0 END) AS `',
          b.`Branch_Name`, '`'      
        )
        ORDER BY o.`Branch_ID`
      ) 
      INTO @sql
    FROM tbl_product as p
    JOIN tbl_orders as o on p.ID = o.Item_ID
    JOIN tbl_branch as b on o.Branch_ID = b.ID;
    SET @sql = CONCAT('SELECT p.Description as item,',@sql,
                      ', SUM(o.Qty) as `Total Qty` FROM tbl_product as p
    JOIN tbl_orders as o on p.ID = o.Item_ID
    JOIN tbl_branch as b on o.Branch_ID = b.ID GROUP BY p.id,p.Description;');
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    
    | item      | Branch 1 | Branch 2 | Branch3 | Branch4 | Branch5 | Branch 6 | Total Qty |
    | --------- | -------- | -------- | ------- | ------- | ------- | -------- | --------- |
    | Product 1 | 12       | 0        | 67      | 1       | 0       | 0        | 80        |
    | Product2  | 3        | 0        | 0       | 0       | 1       | 0        | 4         |
    | Product 3 | 1        | 4        | 0       | 0       | 0       | 0        | 5         |
    | Product 4 | 2        | 0        | 5       | 0       | 0       | 0        | 7         |
    | Product 5 | 0        | 0        | 0       | 0       | 0       | 3        | 3         |
    

    View on DB Fiddle

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-10
      • 2011-12-14
      • 2014-02-15
      • 2019-01-26
      相关资源
      最近更新 更多