对SQL查询进行非规范化并组合列

时间:2013-02-20 16:18:40

标签: sql denormalization

我有一个查询,我需要以一种有趣的方式进行非规范化。

以下是来源:

SELECT
  BILL_Invoice.Invoice_Number as AccountNumber,
  replace(convert(varchar(10), dbo.BILL_Invoice.Invoice_Date,101) ,'/','') as AdmitDate,
  BILL_InvoiceCPT.InvoiceCPT_Code AS CPTCode,
  InvoiceCPT_FeeAmount as ItemCharge
FROM
  dbo.BILL_InvoiceCPT 
  LEFT JOIN dbo.BILL_Invoice
  ON dbo.BILL_InvoiceCPT.Invoice_ID = dbo.BILL_Invoice.Invoice_ID

输出如下:

AccountNumber | AdmitDate  | CPTCode | ItemCharge
38689         | 02192013   | 99213   |     110.00
38689         | 02192013   | 80053   |       0.00
38689         | 02192013   | 86361   |       0.00
38689         | 02192013   | 85025   |       0.00
38689         | 02192013   | 87536   |       0.00
38689         | 02192013   | 93000   |      25.00

我需要的是:

AccountNumber | AdmitDate | TotalCharges | CPTCodes                            | ItemCharges
38689         | 02192013  | 135.00       | 99213;80053;86361;85025;87536;93000 | 110.00;0.00;0.00;0.00;0.00;25.00

这是输入第三方软件应用程序所必需的。我不确定如何正确地反规范化这些信息。 PIVOT功能会这样做吗?

3 个答案:

答案 0 :(得分:5)

MySQL有一个名为GROUP_CONCAT的就绪函数!

它看起来像这样:

SELECT 
 AccountNumber
,AdmitDate
,SUM(TotalCharges)
,GROUP_CONCAT(CPTCode)
,GROUP_CONCAT(ItemCharges)
FROM tbl
WHERE condition
GROUP BY AccountNumber, AdmitDate

答案 1 :(得分:2)

您需要进行聚合字符串连接。这是SQL Server的一个难题。结果如下所示:

with t as (
      SELECT bi.Invoice_Number as AccountNumber, 
             replace(convert(varchar(10), bi.Invoice_Date,101) ,'/','') as AdmitDate,
             InvoiceCPT_FeeAmount as TotalCharges,
             biCPT.InvoiceCPT_Code AS CPTCode, 
             InvoiceCPT_FeeAmount as ItemCharge
      FROM dbo.BILL_InvoiceCPT bicpt LEFT JOIN
           dbo.BILL_Invoice bi
           ON bicpt.Invoice_ID = bi.Invoice_ID
    )
select accountNumber, admitDate,
       STUFF((select ',' + CAST(totalCharges as varchar(255))
              from t
              where t.AccountNumber = t2.AccountNumber
              for xml path ('')
             ), 1, 1, '') as TotalCharges,
       STUFF((select ',' + CAST(itemCharge as varchar(255))
              from t
              where t.AccountNumber = t2.AccountNumber
              for xml path ('')
             ), 1, 1, '') as ItemCharges
from (select distinct accountNumber, admitDate
      from t
     ) t2

注意:我没有测试过这个SQL,因此可能会出现语法错误。

答案 2 :(得分:1)

在PostgreSQL中,您使用string_agg()函数和GROUP BY子句进行反规范化。您还可以使用SUM()来获取总费用。对于任何

SELECT string_agg("CPTCode", ';'), SUM("TotalCharges"), ...
FROM dbo.BILL_InvoiceCPT  LEFT JOIN dbo.BILL_Invoice
ON dbo.BILL_InvoiceCPT.Invoice_ID = dbo.BILL_Invoice.Invoice_ID
GROUP BY "AccountNumber"

没有GROUP BY子句就无法做到这一点,聚合函数就是你的朋友。