MySQL双连接/数据透视表

时间:2018-05-18 20:41:17

标签: mysql sql join pivot-table

这是SQL Fiddle

我有一个表库存,其中包含一些如下所示的数据:

 +--------------+---------+---------------+--------------+------------+------------+
| pmkInventory | fnkPart | inventoryYear | inventoryNum | inventoryR | inventoryC |
+--------------+---------+---------------+--------------+------------+------------+
|            1 |      51 |          2016 |            6 | A          |          4 |
|            2 |    2075 |          2016 |           40 | C          |          4 |
|            3 |      50 |          2016 |            3 | A          |          8 |
|            4 |       3 |          2016 |          600 | F          |          3 |
|            5 |       3 |          2017 |          650 | F          |          3 |
|            6 |     100 |          2016 |            2 | B          |          1 |
|            7 |      50 |          2017 |            5 | A          |          8 |
|            8 |      51 |          2017 |           16 | A          |          4 |
+--------------+---------+---------------+--------------+------------+------------+

每年都有每个部分的计数和位置信息。将有超过2年(不仅仅是2016年和2017年存储),但我只需要一次展示两年。

我需要提出一个SQL语句来返回这样的内容:

+---------+---------------+--------------+------------+------------+---------------+--------------+------------+------------+
| fnkPart | inventoryYear | inventoryNum | inventoryR | inventoryC | inventoryYear | inventoryNum | inventoryR | inventoryC |
+---------+---------------+--------------+------------+------------+---------------+--------------+------------+------------+
|      51 | 2016          | 6            | A          | 4          | 2017          | 16           | A          | 4          |
|    2075 | 2016          | 40           | C          | 4          | NULL          | NULL         | NULL       | NULL       |
|      50 | 2016          | 3            | A          | 8          | 2017          | 5            | A          | 8          |
|       3 | 2016          | 600          | F          | 3          | 2017          | 650          | F          | 3          |
|     100 | 2016          | 2            | B          | 1          | NULL          | NULL         | NULL       | NULL       |
|      40 | NULL          | NULL         | NULL       | NULL       | NULL          | NULL         | NULL       | NULL       |
|     504 | NULL          | NULL         | NULL       | NULL       | NULL          | NULL         | NULL       | NULL       |
+---------+---------------+--------------+------------+------------+---------------+--------------+------------+------------+

从我的阅读中我觉得我需要某种Pivot表,而且由于MySQL没有内置的表,我需要使用CASE语句。 This question讨论了数据透视表,但我很混淆如何在不使用count函数的情况下使用它。我不需要计算任何数据,因为我已将数据存储在数据库中 - 我只需要显示它。

非数据透视表解决方案我提出了一些工作。它正确显示年份,但不显示具有空值的行。我有一个包含数千个零件的零件表。我正在加入库存表。我认为通过执行LEFT JOIN我会得到所有部分,即使库存表中指定年份的数据不存在。

这是:

SELECT p.pmkPart, p.partNumber, 
       i1.fnkPart, i1.inventoryYear, i1.inventoryNum, i1.inventoryR, i1.inventoryC, 
       i2.fnkPart, i2.inventoryYear, i2.inventoryNum, i2.inventoryR, i2.inventoryC
FROM part AS p
LEFT JOIN inventory as i1
       ON p.pmkPart = i1.fnkPart
LEFT JOIN inventory as i2
       ON p.pmkPart = i2.fnkPart
WHERE i1.inventoryYear = 2016
AND i2.inventoryYear = 2017
GROUP BY p.pmkPart

这个查询会给我这样的东西。请注意,它缺少2075100部分,因为它们没有2017年的值。它还排除part表中的其余部分 - 没有inventory表中的值。

+---------+------------+---------+---------------+--------------+------------+------------+---------+---------------+--------------+------------+------------+
| pmkPart | partNumber | fnkPart | inventoryYear | inventoryNum | inventoryR | inventoryC | fnkPart | inventoryYear | inventoryNum | inventoryR | inventoryC |
+---------+------------+---------+---------------+--------------+------------+------------+---------+---------------+--------------+------------+------------+
|      51 | AB-l34     |      51 |          2016 |            6 | A          |          4 |      51 |          2017 |           16 | A          |          4 |
|      50 | AB-l36     |      50 |          2016 |            3 | A          |          8 |      50 |          2017 |            5 | A          |          8 |
|       3 | C-5-BT     |       3 |          2016 |          600 | F          |          3 |       3 |          2017 |          650 | F          |          3 |
+---------+------------+---------+---------------+--------------+------------+------------+---------+---------------+--------------+------------+------------+

有没有人对如何修改现有查询以获得正确结果有任何建议?或者如何创建一个支持我想要的数据透视表?

我选择的年份我需要能够改变,但我只会一次选择两个,2016年和2017年,或2016年和2018年,或2017年和2018年等。

我已经找到了如何使用phpMySQL的组合来做到这一点,但我正在转向一个新平台,其中服务器端脚本不是一个选项,所以需要将所有内容都移到SQL中

1 个答案:

答案 0 :(得分:3)

尝试将年份条件添加到联接本身:

SELECT p.pmkPart, p.partNumber, 
       i1.fnkPart, i1.inventoryYear, i1.inventoryNum, i1.inventoryR, i1.inventoryC, 
       i2.fnkPart, i2.inventoryYear, i2.inventoryNum, i2.inventoryR, i2.inventoryC
FROM part AS p
LEFT JOIN inventory as i1
       ON p.pmkPart = i1.fnkPart
       AND i1.inventoryYear = 2016
LEFT JOIN inventory as i2
       ON p.pmkPart = i2.fnkPart
       AND i2.inventoryYear = 2017

此外,此查询中没有汇总,因此您无需按任何方式进行分组。