将虚拟/占位符数据合并到SQL查询中

问题描述 投票:1回答:1

在我们的SQL Server 2016数据库中,我们有一个Payments表,记录了我们客户每月支付的费用,但由于它们不一定每月支付,我们可能会丢失月数据。

我现在需要为每个客户插入缺少的每月付款数据(即零支付)以获取SSRS报告,因为企业希望在报告上每月查看以评估客户付款频率。

因此,在下面的SQL语句中,我首先创建一个表变量,并为每个月插入一行和零支付金额。然后我创建了一些样本支付数据,包括客户ID,月支付金额和金额。我当时需要做的是最终得到的结果是每个客户有12个条目,每个月一个,显示当月付款或0。

-- Dummy monthly payment data to use for missing months
DECLARE @DummyPayments TABLE
(
    MonthNumber INT,
    Payment MONEY
)

INSERT INTO @DummyPayments 
select 1,0 union
select 2,0 union
select 3,0 union
select 4,0 union
select 5,0 union
select 6,0 union
select 7,0 union
select 8,0 union
select 9,0 union
select 10,0 union
select 11,0 union
select 12,0

-- This (much simplified) data would come from our Payments table
DECLARE @CustomerPayments TABLE
(
    CustomerID INT,
    MonthNumber INT,
    Payment MONEY
)

-- Example customer 1 made payment in months 1,3,6,9
insert into @CustomerPayments values(1,1,100);
insert into @CustomerPayments values(1,3,120);
insert into @CustomerPayments values(1,6,140);
insert into @CustomerPayments values(1,9,95);

-- Example customer 2 made payment in months 2,5,10,12    
insert into @CustomerPayments values(2,2,80);
insert into @CustomerPayments values(2,5,90);
insert into @CustomerPayments values(2,10,130);
insert into @CustomerPayments values(2,12,105);

-- Now I want to join real payments with dummy/missing payments
-- to get payment data for each month in the year.
with cust as
(
    select distinct CustomerID 
    from @CustomerPayments
)
select * from @CustomerPayments cp
union
select c.CustomerID, 
(select dp.MonthNumber
 from @DummyPayments dp 
 where dp.MonthNumber not in (select cp.MonthNumber from @CustomerPayments cp where cp.CustomerID = c.CustomerID)),
 0
from cust c

当我运行它时,我收到一个错误

子查询返回的值超过1。当子查询跟随=,!=,<,<=,>,> =或子查询用作表达式时,不允许这样做。

我认为用联盟做这件事会起作用,我理解错误告诉我,我在每个子查询中得到的结果太多但是使用游标时我不知道如何做到这一点。也许我过于复杂,但如果有人能帮助我,我会很感激。

sql sql-server
1个回答
3
投票

使用cross join生成行,然后使用left join来生成现有结果:

select c.customerid, dp.monthnumber, coalesce(cp.payment, 0) as payment
from (select distinct customerid from @customerpayments cp
     ) c cross join
     @dummypayments dp left join
     @customerpayments cp
     on cp.customerid = c.customerid and
        cp.monthnumber = dp.monthnumber;
© www.soinside.com 2019 - 2024. All rights reserved.