由case语句挫败的SQL Server分组

时间:2014-04-02 21:13:08

标签: sql sql-server sql-server-2008

我的应用程序有Bills,而Bills可能有多个订单项(billItems)。

比尔也可能有一个Copay金额,该金额会被添加到订单项的总数中。

它也可能有Rebill金额,它完全取代订单项。

我有一个需要返回总结算金额的功能。目前,它看起来像这样:

SELECT @billed = (SELECT CASE WHEN b.Rebill=1 THEN ISNULL(b.RebillAmt,0)
        WHEN b.HasCopay=1 THEN ISNULL(SUM(bi.Amount),0) + ISNULL(b.CopayAmt,0)
        ELSE ISNULL(SUM(bi.Amount),0) END AS TotalBilled
    FROM BillItems bi 
        INNER JOIN Bills b ON b.BillID=bi.BillID
        INNER JOIN Procedures p ON p.ProcedureID=b.ProcedureID
    WHERE p.CaseID = @CASEID
    AND     p.StatusID=3
    GROUP BY b.CaseID,b.Rebill,b.RebillAmt,b.HasCopay,b.CopayAmt)
RETURN @billed

如果没有自付额或重生金额,该函数将返回一个总额。但是,如果有自付额或重新计算金额,内部SELECT会返回每张账单的记录,该记录包含自付额或重新开具,以及一张记录,其中包含没有自付额或重新开具金额的账单。

我应该如何重申这一点,以便为每个" Case"

获得一个总计费金额?

(这是SQL Server 2008安装。)

谢谢,

汤姆

以下是进一步的信息:第一,业务目的和规则。

考虑一下医疗过程。作为参考,称之为"案例。"

每个病例都会有一系列治疗(程序)。对于给定的程序,将收到一份或多份票据。对于每个账单,可能有一个或多个结算行项目(BillItems),每个项目都有一个金额。

对于每张帐单,总的最终结算金额为:

  • 所有相关BillItems的总额,或
  • 如果Bill.HasCopay标志为真,并且有一个CopayAmt,则所有相关BillItem金额加上CopayAmt的总和;或
  • 如果Bill.Rebill标志为true并且有RebillAmt,则RebillAmt

因此,如果该条例草案要被重新抨击,那么#34; RebillAmt是总计费。如果存在CopayAmt,则将其添加到BillItem的总数中。否则,我们只是总计BillItems。

目标是根据对每个账单应用上述规则,汇总案件的单一总计费金额。

DDL如下。 Case表已被省略,因为它有许多不相关的字段。可以说,它由其他表中的CaseID关系表示。

这些表没有规范化,因为Case之间存在冗余关系。这是为了便于报告而故意完成的。你当然可以不同意这个设计,但这就是它的设计方式。

下面的代码中没有显示外键关系,但是从上面的规则可以看出,案例中的程序具有包含BillItems的票据。

最后,为了清楚起见," p.StatusID = 3"在原始声明中,只是标识已经批准的程序。"所有其他人都被忽略了。

非常感谢你的帮助。希望这将是足够的信息,使问题更容易回答。这是代码:

CREATE TABLE Procedures (
ProcedureID int IDENTITY(1,1) NOT NULL,
RequestID int NOT NULL,
StatusID int,
ProviderLocationID int DEFAULT ((0)) NOT NULL,
Description varchar(3000),
CPTcodes varchar(500),
Rejected bit DEFAULT ((0)) NOT NULL,
CreateDate datetime DEFAULT (getdate()) NOT NULL,
CreatedByID int,
ChangeDate datetime DEFAULT (getdate()) NOT NULL,
ChangeUserID int,
ApprovalDate datetime,
ApprovalCode varchar(25),
ShowCPTCodes bit DEFAULT ((1)) NOT NULL,
DispositionDate datetime,
PreviouslyApproved bit DEFAULT ((0)) NOT NULL,
SubmissionDate datetime,
DenialDate datetime,
IsPT bit DEFAULT ((0)) NOT NULL,
DenialReason varchar(1000),
PriorProcedure bit DEFAULT ((0)) NOT NULL,
UseCommonTreatmentDates bit DEFAULT ((1)) NOT NULL,
IsComplete bit DEFAULT ((0)) NOT NULL,
CommonTreatmentDate datetime,
TreatmentNoteReceived varchar(25) DEFAULT ('No') NOT NULL,
TreatmentNoteRead bit DEFAULT ((0)) NOT NULL,
TreatmentNoteReceivedDate datetime,
TreatmentNoteReadDate datetime,
InvoiceReceived varchar(25),
InvoiceReceivedDate datetime,
CaseID int DEFAULT ((0)) NOT NULL,
TreatmentDate datetime,
ScheduledDate datetime,
PTRemoved bit DEFAULT ((0)) NOT NULL,
ProviderID int DEFAULT ((0)) NOT NULL,
TherapyGroupID int DEFAULT ((0)) NOT NULL,
SendDemographics bit DEFAULT ((0)) NOT NULL,
SendOrder bit DEFAULT ((0)) NOT NULL,
TreatmentNoteNotNeeded bit DEFAULT ((0)) NOT NULL,
PRIMARY KEY (ProcedureID)

);

CREATE TABLE Bills (
BillID int IDENTITY(1,1) NOT NULL,
InvoiceID int DEFAULT ((0)),
CaseID int NOT NULL,
ProcedureID int NOT NULL,
TherapyGroupID int DEFAULT ((0)) NOT NULL,
ProviderID int NOT NULL,
Description varchar(1000),
ServiceDescription varchar(255),
BillReferenceNumber varchar(100),
TreatmentDate datetime,
DateBilled datetime,
DateBillReceived datetime,
DateBillApproved datetime,
HasCopay bit DEFAULT ((0)) NOT NULL,
CopayAmt money,
Rebill bit DEFAULT ((0)) NOT NULL,
RebillAmt money,
IncludeInDemand bit DEFAULT ((1)) NOT NULL,
CreateDate datetime DEFAULT (getdate()) NOT NULL,
CreatedByID int,
ChangeDate datetime,
ChangeUserID int,
PRIMARY KEY (BillID)

);

CREATE TABLE BillItems (
BillItemID int IDENTITY(1,1) NOT NULL,
BillID int NOT NULL,
ItemDescription varchar(1000),
Amount money,
WillNotBePaid bit DEFAULT ((0)) NOT NULL,
CreateDate datetime DEFAULT (getdate()),
CreatedByID int,
ChangeDate datetime,
ChangeUserID varchar(25),
PRIMARY KEY (BillItemID)

);

2 个答案:

答案 0 :(得分:0)

试试这个:

select
    SUM(Amount) as TotalBilled
from (
    select      
        case 
            when b.Rebill = 1 then coalesce(b.RebillAmt, 0)
            when b.HasCopay = 1 then coalesce(bi.Amount, 0) + coalesce(b.CopayAmt, 0)
            else coalesce(bi.Amount, 0)
        end as Amount
    FROM BillItems bi 
        INNER JOIN Bills b ON b.BillID=bi.BillID
        INNER JOIN Procedures p ON p.ProcedureID=b.ProcedureID
    WHERE p.CaseID = @CASEID
        AND p.StatusID=3
) x

答案 1 :(得分:0)

我找到了至少一种方法来实现我的需要。由于Bills和相关BillItems的每个组合可能具有从BillItems的总计金额中得到的总额,从总计加上的自付额,或者来自重新计算金额,所以必须单独检查这些可能性中的每一个。

对于一个案例的法案积累,任何这些考试的结果("是否总共基于反叛?")可能是一个空的记录集。

因此,我构建了一个包含COALESCE语句组合的解决方案,以确保在没有返回记录的情况下检查任何可能的组合会导致零。

然后添加检查三种可能性中的每一种的结果。

这是我的解决方案。如果有人看到了瑕疵或更好的方式,请告诉我。

CREATE FUNCTION [dbo].[fnTotalBilled]  (@CASEID INT)
RETURNS MONEY AS
BEGIN
DECLARE @billed MONEY

SELECT @billed  = (SELECT COALESCE((SELECT COALESCE(sum(bi.Amount),0)
FROM BillItems bi INNER JOIN Bills b ON b.BillID=bi.BillID
    INNER JOIN Procedures p on p.ProcedureID=b.ProcedureID
WHERE b.CaseID=@CASEID
AND p.StatusID=3
AND b.HasCopay=0
AND b.Rebill=0),0))
+
(SELECT COALESCE((SELECT sum(bi.Amount) + COALESCE(b.CopayAmt,0)
FROM BillItems bi INNER JOIN Bills b ON b.BillID=bi.BillID
    INNER JOIN Procedures p on p.ProcedureID=b.ProcedureID
WHERE b.CaseID=@CASEID
AND p.StatusID=3
AND b.HasCopay=1
GROUP BY b.CaseID,b.CopayAmt),0))
+
(SELECT COALESCE((SELECT sum(COALESCE(b.RebillAmt,0))
FROM Bills b
    INNER JOIN Procedures p on p.ProcedureID=b.ProcedureID
WHERE b.CaseID=@CASEID
AND p.StatusID=3
AND b.Rebill=1),0))

RETURN @billed
END;