给出3个表(合同,服务,合同_服务)
作为多种服务的合同以4种类型组织(现在,将会有更多)。
我需要的是获得所有价格的SUM()GROUP BY service_type FOR EACH Contract,每份合约一行。
contracts.id, 'total_service_type_1', 'total_service_type_2', 'total_service_type_3', 'total_service_type_4'
这是我到目前为止所得到的
SELECT c.id,s.servicetype_id,sum(cs.price)as total
FROM contracts c
LEFT JOIN addresses a ON a.id = c.address_id
LEFT JOIN contracts_services cs ON cs.contract_id = c.id
LEFT JOIN services s ON s.id = cs.service_id
WHERE s.servicetype_id IS NOT NULL
GROUP BY c.id,s.servicetype_id
ORDER BY c.id
如何将这些查询结果转换为单个合约行的列?
答案 0 :(得分:1)
你不能在MySQL(或任何SQL风格)中拥有动态列。因此,您只能通过将每个服务类型添加为查询的新join
来实现此目的。为简洁起见,我在下面的示例中添加了两种服务类型,对于额外的服务类型,只需添加更多LEFT JOIN
。
最后说:有你的痛苦。这个解决方案绝对不灵活。对于您添加的每种新服务类型,您必须再次编辑查询。您应该在编程语言中寻找解决方案。因此,当您从MySQL
调用PHP
时,请使用您已有的查询并且工作得非常好,并使用PHP
重写您的数组(动态),以便获得所需的输出(用你正在使用的编程语言替换PHP
。
SELECT
c.id AS contractId,
SUM(cs1.price) AS service1Total,
SUM(cs2.price) AS service2Total
FROM contracts c
JOIN services s
LEFT JOIN contracts_services cs1 ON
cs1.contract_id = c.id
AND cs1.service_id = s.id
AND s.servicetype_id = 1
LEFT JOIN contracts_services cs2 ON
cs2.contract_id = c.id
AND cs2.service_id = s.id
AND s.servicetype_id = 2
GROUP BY c.id
SQLFiddle:http://sqlfiddle.com/#!9/4f9a9c/2/0
注意:如果您希望SUM(cs1.price)
超过IFNULL(SUM(cs1.price), 0)
,则可以将0
替换为NULL
。
编辑:替代查询,在阅读Paul Spiegel的评论(关于数据透视表)后,连接较少,因此更有可能对您的数据库服务器友好。但是,与上述查询具有相同的缺点:每次添加新服务类型时都必须对其进行编辑。
SELECT
c.id AS contractId,
SUM(IF(s.servicetype_id = 1, cs.price, 0)) AS service1Total,
SUM(IF(s.servicetype_id = 2, cs.price, 0)) AS service2Total
FROM contracts c
LEFT JOIN contracts_services cs ON cs.contract_id = c.id
LEFT JOIN services s ON cs.service_id = s.id
GROUP BY c.id