简体   繁体   English

MySQL中的矩阵/交叉表/数据透视查询

[英]matrix/crosstab/pivot query in mySQL

I have a Bill table like this 我有一个这样的比尔表

BillNo - 1, ServiceCode -1, ServiceName - 'Lab test' , ItemAmount -30 BillNo-1,ServiceCode -1,ServiceName-'Lab test',ItemAmount -30

BillNo -1, ServiceCode -2, ServiceName -'Consultation', ItemAmount -70 BillNo -1,ServiceCode -2,ServiceName -'Consultation',ItemAmount -70

I need output like this 我需要这样的输出

Bill No -1, Total Bill Amount-100 , Lab Test-30, Consultation-70, Drugs-0, Misc-0 法案编号-1,法案总金额100,实验室测试30,咨询70,药品-0,杂项-0

So basically i need the Bill Amount which is the SUM of all ItemAmount Grouped by BillNo. 所以基本上我需要帐单金额,这是按BillNo分组的所有ItemAmount的总和。 Then in the same row i need to distribute this Bill Amount to the 4 ServiceNames. 然后在同一行中,我需要将此账单金额分配给4个ServiceName。 So 100 gets distributed as 30 for Lab test and 70 for Consultation. 因此,分发了100个,其中30个用于实验室测试,另外70个用于咨询。

This gave me what i want but it is not optimal. 这给了我我想要的,但不是最佳的。

SELECT
    BD.BILLNO AS BN,
    SUM(BD.ITEMAMOUNT) AS "Bill Amount",
    (SELECT SUM(BD.ITEMAMOUNT) FROM BILLDETAILS BD
        WHERE SERVICENAME LIKE '%Lab%'
        AND BD.BILLNO = BN ) AS "Lab",
    (SELECT SUM(BD.ITEMAMOUNT) FROM BILLDETAILS BD
        WHERE SERVICENAME LIKE '%Consult%'
        AND BD.BILLNO = BN ) AS "Consultation",
    (SELECT SUM(BD.ITEMAMOUNT) FROM BILLDETAILS BD
        WHERE SERVICENAME LIKE '%Procedure%'
        AND BD.BILLNO = BN ) AS "Procedures",
    (SELECT SUM(BD.ITEMAMOUNT) FROM BILLDETAILS BD
        WHERE SERVICENAME LIKE '%Drugs%'
        AND BD.BILLNO = BN ) AS "Drugs",
    (SELECT SUM(BD.ITEMAMOUNT) FROM BILLDETAILS BD
        WHERE SERVICENAME NOT LIKE '%Lab%'
        AND SERVICENAME NOT LIKE 'Consult%'
        AND SERVICENAME NOT LIKE '%Procedure%'
        AND SERVICENAME NOT LIKE '%Drugs%'
        AND BD.BILLNO = BN )AS "Miscellaneous"
FROM BILLDETAILS BD
GROUP BY BD.BILLNO

How can i improve this mySQL query ? 我如何改善这个mySQL查询?

Thanks. 谢谢。 Chak. k

Try this: 尝试这个:

SELECT
  BillNo,
  LabTest,
  Consultation,
  Drugs,
  Misc,
  LabTest + Consultation + Drugs + Misc AS BillAmount
FROM (
  SELECT
    BillNo,
    IFNULL(GROUP_CONCAT(IF(ServiceCode=1, ItemAmount, NULL)), 0) AS LabTest,
    IFNULL(GROUP_CONCAT(IF(ServiceCode=2, ItemAmount, NULL)), 0) AS Consultation,
    IFNULL(GROUP_CONCAT(IF(ServiceCode=3, ItemAmount, NULL)), 0) AS Drugs,
    IFNULL(GROUP_CONCAT(IF(ServiceCode=4, ItemAmount, NULL)), 0) AS Misc
  FROM bill
  GROUP BY BillNo
) AS services;

I have tested ServiceCode rather than ServiceName , as I have assumed that the two are related. 我已经测试了ServiceCode而不是ServiceName ,因为我假设两者是相关的。 If they are not related, just change the comparison as necessary. 如果它们不相关,请根据需要更改比较。

Test data: 测试数据:

INSERT INTO bill (BillNo, ServiceCode, ServiceName, ItemAmount) VALUES
(1, 1, 'Lab Test', 30),
(1, 2, 'Consultation', 70),
(2, 1, 'Lab Test', 40),
(2, 2, 'Consultation', 20),
(2, 3, 'Drugs', 15),
(2, 4, 'Misc', 25);

Results: 结果:

+--------+---------+--------------+-------+------+------------+
| BillNo | LabTest | Consultation | Drugs | Misc | BillAmount |
+--------+---------+--------------+-------+------+------------+
|      1 | 30      | 70           | 0     | 0    |        100 |
|      2 | 40      | 20           | 15    | 25   |        100 |
+--------+---------+--------------+-------+------+------------+

You can try this, though I havnt test it- 您可以尝试一下,尽管我已经对其进行了测试-

SELECT BillNo,count(ItemAmount) as "Total Bill Amount", 
(CASE ServiceName WHEN 'Lab test' THEN count(ServiceName) as "Lab Test" 
WHEN 'Consultation' THEN count(ServiceName) as Consultation  
WHEN 'Drugs' THEN count(ServiceName) as Drugs 
ELSE count(ServiceName) as Misc END CASE) 
from Bill group by BillNo;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM