这应该是简单的SQL查询让我疯狂

时间:2016-02-26 14:22:44

标签: sql sql-server sum variance

我正在研究一个理论上应该简单的问题的SQL查询,但它对我来说是一个挑战。

使用当前的存储过程作为模板,我需要做的就是添加返回的方差作为总接收数。我已经创建了本地表,并在该表中输入了总收入应该从中减去的金额,以便创建差异。

但每次我运行时,数字都会错误地返回并且也会多次返回。

基本上我只需要能够返回每个基金的总收益并从其目标(本地表)中减去它,这就是方差。我不需要组成细节,只需要基金详情。

以下是我正在处理的存储过程:

 (
    @trans_start_dt datetime = NULL,
    @trans_end_dt datetime = NULL,
    @fund_str varchar(4000) = null,
    @fyear_str varchar(4000) = null,
    @campaign_str varchar(4000) = null,
    @designation_str varchar(4000) = null,
    @appeal_str varchar(4000) = null,
    @mode int = 1,      -- now default to Fund
    @show_constituent_detail char(1) = 'N',
    @list_no int,
    @list_acts_upon int = 1,
    @channel_str varchar(4000) = null,
    @cont_start_dt datetime = null,
    @cont_end_dt datetime = null,
    @posting_start_dt datetime = null,
    @posting_end_dt datetime = null
    )
AS
SET NOCOUNT ON
/*******************************************************************************
Combines into a single report procedure that works with a single datawindow.

Additional parameters @designation_str, @fyear_str and @campaign_str added for additional filtering.

New modes group by Campaign or FYear. New report moves "Constituent" mode out of the @mode parameter and into "Show Constituent Detail".  The legacy mode "Constituent" can be run using Mode 1 (Fund) and Show Constituent Detail = 'Y'.

Note:  Former mode "Constituent" is now achieved by using Mode = Fund and Show Constituent Detail = 'Yes'.


Modes
    1 Fund
    3 Payment
    4 Campaign, Fund
    5 Campaign, Fund, Designation

Exec [dbo].[RP_FUND_ACTIVITY_REPORT] 
    @trans_start_dt = '2000-01-01',
    @trans_end_dt = '2011-01-01',
    @fund_str = null,
    @fyear_str = null,
    @campaign_str = null,
    @designation_str = null,
    @appeal_str = null,
    @mode = 3,
    @list_no = null,
    @channel_str = null

***************************************************************************************/
Set Transaction Isolation Level Read Uncommitted

If @mode = 2
  Begin
    Raiserror('Group By mode Constituent (2) is no longer supported.  Use group by Fund, and set Show Constituent Detail to Yes.', 11, 2)   
    RETURN
  End

If @mode not in (1,3,4,5)
  Begin
    Raiserror('Mode %i is not a valid setting.', 11, 2, @mode)  
    RETURN
  End

If @list_no is NOT NULL and not Exists (Select * From dbo.VS_LIST Where list_no = @list_no)
  Begin
    Raiserror('List number %i is not a valid list.', 11, 2, @list_no)   
    RETURN
  End

If (@posting_start_dt is NULL and @posting_end_dt is NOT NULL)
    or (@posting_start_dt is NOT NULL and @posting_end_dt is NULL)
  Begin
    Raiserror('Posting Start and End dates must both have a value if used.', 11, 2) 
    RETURN
  End

Declare @filter_by_posting_date bit

If @posting_start_dt is NOT NULL and @posting_end_dt is NOT NULL
    Select @filter_by_posting_date = 1
Else
    Select @filter_by_posting_date = 0

Declare @fund Table (fund_no int, fund_desc varchar(30) null)
Declare @channel Table(id int, description varchar(30) null)
Declare @appeal Table(appeal_no int, fund_desc varchar(30) null)
Declare @cont_designation Table (id int, description varchar(30) null)

IF @fund_str is null or Coalesce(Datalength(ltrim(@fund_str)),0) = 0
    Insert  into @fund (fund_no, fund_desc)
    Select  fund_no, description
    From    [dbo].vs_fund
Else
    Insert  into @fund (fund_no, fund_desc)
    Select  fund_no, description
    from    [dbo].vs_fund
    where   charindex(',' + convert(varchar, fund_no) + ',' , ',' + @fund_str + ',') > 0

IF @channel_str is null or Coalesce(Datalength(ltrim(@channel_str)),0) = 0
    Insert  into @channel
    Select  id, description
    From    [dbo].tr_sales_channel
Else
    Insert  into @channel
    Select  id, description
    from    [dbo].tr_sales_channel
    where   charindex(',' + convert(varchar, id) + ',' , ',' + @channel_str + ',') > 0


IF @appeal_str is null or Coalesce(Datalength(ltrim(@appeal_str)),0) = 0
    Insert  into @appeal
    Select  appeal_no, description
    From    [dbo].t_appeal
Else
    Insert  into @appeal
    Select  appeal_no, description
    from    [dbo].t_appeal
    where   charindex(',' + convert(varchar, appeal_no) + ',' , ',' + @appeal_str + ',') > 0


IF @designation_str is null or Coalesce(Datalength(ltrim(@designation_str)),0) = 0
  Begin
    Insert into @cont_designation (id, description)
    Values (0, '(none)')

    Insert  into @cont_designation(id, description)
    Select  id, description
    From    [dbo].TR_CONT_DESIGNATION
  End
Else
    Insert  into @cont_designation(id, description)
    Select  id, description
    from    [dbo].TR_CONT_DESIGNATION
    where   charindex(',' + convert(varchar, id) + ',' , ',' + @designation_str + ',') > 0

Create  table  #transactions(
    sequence_no int null, 
    trn_type int null,
    fund_no int null,
    fyear int null,
    campaign_no int null,
    campaign varchar(30) null,
    cont_designation_id int,
    batch_no int null,
    posted_ind bit,
    ref_no int null,
    cont_dt datetime null,
    trn_dt datetime null,
    pledge money null,
    pledge_payment money null,
    gift money null,
    restricted money null,
    write_off money null,
    total_received money null,
    channel int null,
    customer_no int null,
    pmt_method_id int null,
    pmt_method varchar(30) null,
    pledge_pmt_amt money null,
    gift_pmt_amt money null,
    creditee_type int null, 
    creditee_type_desc varchar(30) null,
    creditee_no int null, 
    creditee_name varchar(80) null
    )

Create index aaa on #transactions(customer_no, fund_no)

Insert  into #transactions (sequence_no, trn_type, fund_no, fyear, campaign_no, campaign, cont_designation_id, batch_no, posted_ind, ref_no, 
        cont_dt, trn_dt, pledge, pledge_payment, gift, restricted, write_off, total_received, channel, customer_no)
Select  a.sequence_no,
    a.trn_type,
    a.fund_no,
    cm.fyear,
    a.campaign_no,
    cm.description,
    Coalesce(d.cont_designation, 0),        -- Default no designation to 0
    a.batch_no,
    Case When a.posted_status = 'Y' Then 1 Else 0 End,
    a.ref_no,
    d.cont_dt,
    a.trn_dt,
    pledge = CASE WHEN trn_type in (2, 5) THEN a.trn_amt ELSE 0 END,
    pledge_payment = CASE WHEN trn_type in (3, 6) THEN a.trn_amt ELSE 0 END,
    gift = CASE WHEN trn_type in (1, 4, 61) THEN a.trn_amt ELSE 0 END,
    restricted = CASE WHEN trn_type = 10 THEN a.trn_amt
                    When trn_type = 11 Then a.trn_amt * -1
                    Else 0 End,
    write_off = CASE WHEN trn_type in (7) THEN a.trn_amt ELSE 0 END, 
    total_received = CASE WHEN trn_type in (1, 3, 4, 6, 61) THEN trn_amt ELSE 0 END,
    channel = e.id,
    customer_no = d.customer_no
from    [dbo].t_transaction a 
    JOIN @fund b ON a.fund_no = b.fund_no
    LEFT JOIN dbo.FT_SPLIT_LIST(@appeal_str, ',') ap on a.appeal_no = ap.element
    JOIN [dbo].T_CONTRIBUTION d ON a.ref_no = d.ref_no
    JOIN dbo.T_BATCH ba on a.batch_no = ba.batch_no
    JOIN dbo.T_CAMPAIGN cm on d.campaign_no = cm.campaign_no
    JOIN @cont_designation cd on d.cont_designation = cd.id or (d.cont_designation is NULL and cd.id = 0)
    JOIN @channel e ON d.channel = e.id
where   a.trn_type in (1, 2, 3, 4, 5, 6, 7, 10, 11, 61)  
    and (Coalesce(@trans_start_dt, @trans_end_dt, null) is NULL or a.trn_dt between @trans_start_dt  and @trans_end_dt) --FP1675.  handling null trans date parameters
    and d.cont_dt between Coalesce(@cont_start_dt, '1900-01-01') and Coalesce(@cont_end_dt, '2999-12-31')
    and (@filter_by_posting_date = 0 or ba.posted_dt between @posting_start_dt and @posting_end_dt)
    and (@appeal_str is NULL or ap.ElementId > 0)


If @campaign_str is NOT NULL
    Delete From #transactions 
    Where campaign_no NOT IN (Select element From dbo.FT_SPLIT_LIST(@campaign_str, ','))

If @mode = 3 -- Payment (includes gift change transaction amounts where no payment method is involved)
  Begin
    Insert into #transactions (sequence_no, trn_type, fund_no, fyear, campaign_no, campaign, cont_designation_id, batch_no, posted_ind, ref_no, 
        cont_dt, trn_dt, pledge, pledge_payment, gift, restricted, write_off, total_received, 
        channel, customer_no, pmt_method_id, pmt_method, pledge_pmt_amt, gift_pmt_amt)
    Select t.sequence_no,
            t.trn_type,
            t.fund_no,
            t.fyear,
            t.campaign_no,
            t.campaign,
            t.cont_designation_id,
            t.batch_no,
            t.posted_ind,
            t.ref_no,
            t.cont_dt,
            t.trn_dt,
            0,
            0,
            0,
            0,
            0,
            0,
            t.channel,
            t.customer_no,
            Coalesce(p.pmt_method, -1),
            Coalesce(pm.description, '(Gift Change)'),
            Case When t.trn_type in (3,6) Then Coalesce(p.pmt_amt, t.total_received) Else 0 End,
            Case When t.trn_type in (1,4,61) Then Coalesce(p.pmt_amt, t.total_received) Else 0 End
    From #transactions t
        LEFT JOIN dbo.T_PAYMENT p on t.sequence_no = p.sequence_no
        LEFT JOIN dbo.TR_PAYMENT_METHOD pm on p.pmt_method = pm.id
    Where t.trn_type in (1, 3, 4, 6, 61)
  End


If @list_no > 0
  Begin
    If @list_acts_upon = 1
      Begin
        Delete From #transactions
        Where customer_no not in (Select customer_no From dbo.T_LIST_CONTENTS Where list_no = @list_no)
      End
    Else
      Begin
        Delete  a
        From    #transactions a
            JOIN T_CONTRIBUTION b ON a.ref_no = b.ref_no
        Where   (b.initiator_no is not null and b.initiator_no not in (Select customer_no From dbo.T_LIST_CONTENTS Where list_no = @list_no))
            OR
            (b.initiator_no is null and b.customer_no not in (Select customer_no From dbo.T_LIST_CONTENTS Where list_no = @list_no))

      End
  End




If @show_constituent_detail = 'Y'
  Begin
    Update a    -- If more than ONE creditee per contribution, the selection here is 1-1 and arbitrary (well, based on page file)
    Set creditee_no = b.creditee_no,
        creditee_type = c.id,
        creditee_type_desc = c.descriptiuon,
        creditee_name = dn.display_name
    From    #transactions a
        JOIN dbo.T_CREDITEE b ON a.ref_no = b.ref_no
        JOIN dbo.TR_CREDITEE_TYPE c ON b.creditee_type = c.id
        JOIN dbo.FT_CONSTITUENT_DISPLAY_NAME() dn on b.creditee_no = dn.customer_no
  End


If @fyear_str is NOT NULL
  Begin
    Delete From #transactions
    Where fyear NOT IN (Select element From dbo.FT_SPLIT_LIST(@fyear_str, ','))
  End

If @mode in (1,3)
    Update #transactions
    Set fyear = null,
        campaign_no = null,
        campaign = NULL,
        cont_designation_id = null

If @show_constituent_detail = 'Y'
    Select  trn_count = Case When a.pmt_method_id is NOT NULL Then 0 Else 1 End,        
            a.pledge,
            a.pledge_payment,
            a.gift,
            a.restricted,
            a.write_off,
            a.total_received,
            a.batch_no,
            a.ref_no,
            a.cont_dt,
            a.trn_dt,
            fund_no = a.fund_no,
            fund_desc = f.fund_desc,
            a.fyear,
            a.campaign_no,
            a.campaign,
            a.cont_designation_id,
            cont_designation = d.description,
            channel_id = a.channel,
            channel_desc = ch.description,
            a.pmt_method_id,
            a.pmt_method,           
            a.pledge_pmt_amt,
            a.gift_pmt_amt,
            pmt_count = case When a.pmt_method_id is NOT NULL Then 1 Else 0 End,
            c.customer_no,
            c.lname,
            c.fname,
            a.creditee_type,
            a.creditee_type_desc,
            a.creditee_no,
            a.creditee_name,
            dn.display_name,
            dn.sort_name
    From #transactions a
        JOIN @fund f on a.fund_no = f.fund_no
        LEFT JOIN @channel ch on a.channel = ch.id
        LEFT JOIN @cont_designation d on a.cont_designation_id = d.id
        LEFT JOIN dbo.T_CUSTOMER c on a.customer_no = c.customer_no
        LEFT JOIN dbo.FT_CONSTITUENT_DISPLAY_NAME() dn on c.customer_no = dn.customer_no
Else
    Select  trn_count = SUM(Case When a.pmt_method_id is NOT NULL Then 0 Else 1 End),       
            pledge = sum(a.pledge),
            pledge_payment = sum(a.pledge_payment),
            gift = sum(a.gift),
            restricted = sum(a.restricted),
            write_off = sum(a.write_off),
            total_received = sum(a.total_received),
            batch_no = null,
            ref_no = null,
            cont_dt = null,
            trn_dt = null,
            fund_no = a.fund_no,
            fund_desc = max(f.fund_desc),
            a.fyear,
            a.campaign_no,
            campaign = MAX(a.campaign),
            a.cont_designation_id,
            cont_desisgnation = max(d.description),
            channel_id = null,
            channel_desc = null,
            a.pmt_method_id,
            pmt_method = MAX(a.pmt_method),
            pledge_pmt_amt = SUM(a.pledge_pmt_amt),
            gift_pmt_amt = SUM(a.gift_pmt_amt),
            pmt_count = SUM(case When a.pmt_method_id is NOT NULL Then 1 Else 0 End),
            customer_no = null,
            lname = null,
            fname = null,
            creditee_type = null,
            creditee_type_desc = null,
            creditee_no = null,
            creditee_name = null,
            display_name = null,
            sort_name = null
    From #transactions a
        JOIN @fund f on a.fund_no = f.fund_no
        LEFT JOIN @cont_designation d on a.cont_designation_id = d.id
    Group by a.fyear, a.campaign_no, a.fund_no, a.cont_designation_id, a.pmt_method_id
RETURN

我需要添加的表是一个名为ISTA_VARIANCE_GOALS的简单本地表,它只需要将proj_amt(GOAL)反映给SUM。它有proj_amt,fund_no,campaign_no,但我认为我需要的只是proj_amt。

就是这样。 但我似乎无法使其发挥作用。 它驱使我c-r-a-z-y。****

0 个答案:

没有答案