我得到的是3张桌子。
我们有一个'订单'表,然后可以有'order_extras'。 'extras'表存储附加组件的名称和价格,'order_extras'基本上包含主键,订单ID和额外ID。
粗略的图形表示如下:
以此为例,我们假设'extras'表中填充了3个额外的项目,在此阶段名称和价格无关紧要。
我想要做的是获取所有订单,但每个额外项目的名称都有额外的列。如果该商品已被购买(也在order_extras表中链接),它将显示价格,否则它将为空/ null。
这甚至可能吗?我一直在寻找数据透视表,但有关这类事情的信息似乎有些不稳定。任何信息或建议将不胜感激!
示例数据
附加功能:
+----+------------------+--------+
| id | name | price |
+----+------------------+--------+
| 1 | Insurance | 59.95 |
| 2 | Lifetime Updates | 79.95 |
| 3 | Phone Support | 124.95 |
+----+------------------+--------+
订单:
+----+------------+
| id | customer |
+----+------------+
| 1 | John Smith |
| 2 | Bob Newbie |
| 3 | Bill Jobs |
| 4 | Ray Stantz |
+----+------------+
order_extras:
+----+----------+----------+
| id | order_id | extra_id |
+----+----------+----------+
| 1 | 4 | 2 |
| 2 | 3 | 1 |
| 3 | 3 | 3 |
| 4 | 1 | 1 |
+----+----------+----------+
期望的输出:
+----------+----------------+-----------+------------------+---------------+
| order.id | order.customer | Insurance | Lifetime Updates | Phone Support |
+----------+----------------+-----------+------------------+---------------+
| 1 | John Smith | 59.95 | 0 | 0 |
| 2 | Bob Newbie | 0 | 0 | 0 |
| 3 | Bill Jobs | 59.95 | 0 | 124.95 |
| 4 | Ray Stantz | 0 | 79.95 | 0 |
+----------+----------------+-----------+------------------+---------------+
答案 0 :(得分:2)
不幸的是,MySQL没有 pivot 函数,但可以使用带有CASE
表达式的聚合函数进行复制。
如果您有一个已知数量的extras
,那么您可以对查询进行硬编码:
select o.id,
o.customer,
max(case when e.name = 'Insurance' then e.price else 0 end) Insurance,
max(case when e.name = 'Lifetime Updates' then e.price else 0 end) `Lifetime Updates`,
max(case when e.name = 'Phone Support' then e.price else 0 end) `Phone Support`
from orders o
left join order_extras oe
on o.id = oe.order_id
left join extras e
on oe.extra_id = e.id
group by o.id, o.customer
对于您的情况,您似乎将拥有未知数量的值。如果是这种情况,那么您将需要使用预准备语句来生成动态sql:
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(CASE WHEN e.name = ''',
name,
''' THEN e.price else 0 END) AS `',
name, '`'
)
) INTO @sql
FROM extras;
SET @sql
= CONCAT('SELECT o.id,
o.customer, ', @sql, '
from orders o
left join order_extras oe
on o.id = oe.order_id
left join extras e
on oe.extra_id = e.id
group by o.id, o.customer');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
这两个版本都会给出结果:
| ID | CUSTOMER | INSURANCE | LIFETIME UPDATES | PHONE SUPPORT |
------------------------------------------------------------------
| 1 | John Smith | 59.95 | 0 | 0 |
| 2 | Bob Newbie | 0 | 0 | 0 |
| 3 | Bill Jobs | 59.95 | 0 | 124.95 |
| 4 | Ray Stantz | 0 | 79.95 | 0 |
答案 1 :(得分:1)
试试这个。
select o.id , o.customer ,
max(if(e.name = 'Insurance' , round(e.price,2), 0)) as Insurance,
max(if(e.name = 'Lifetime Updates' , round(e.price,2), 0)) as Lifetime_Updates,
max(if(e.name = 'Phone Support' , round(e.price,2), 0)) as Phone_Support
from orders o
left join order_extras oe
on o.id = oe.order_id
left join Extras e
on oe.extra_id = e.id
group by o.id, o.customer
输出是:
ID CUSTOMER INSURANCE LIFETIME_UPDATES PHONE_SUPPORT
1 John Smith 59.95 0 0
2 Bob Newbie 0 0 0
3 Bill Jobs 59.95 0 124.95
4 Ray Stantz 0 79.95 0