mySQL中的matrix / crosstab / pivot查询

时间:2010-07-23 03:43:54

标签: mysql

我有一张像这样的比尔表

BillNo - 1,ServiceCode -1,ServiceName - '实验室测试',ItemAmount -30

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

我需要这样的输出

Bill No -1,Total Bill Amount-100,Lab Test-30,Consultation-70,Drugs-0,Misc-0

所以基本上我需要Bill Amount,它是由BillNo分组的所有ItemAmount的SUM。然后在同一行我需要将此Bill Billount分配给4个ServiceNames。因此,实验室测试分配为30分,咨询分配分配为70分。

这给了我想要的东西,但它不是最佳的。

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

如何改进mySQL查询?

感谢。 泽。

2 个答案:

答案 0 :(得分:1)

试试这个:

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;

我测试了ServiceCode而不是ServiceName,因为我认为这两者是相关的。如果它们不相关,只需根据需要更改比较。

测试数据:

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);

结果:

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

答案 1 :(得分:0)

你可以试试这个,虽然我没有测试itp>

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;