You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL函数子查询报错:构建月度营收视图受阻求助

解决子查询返回多行的报错问题

Hey,我一眼就揪出问题所在了——你遇到的Msg 512报错,核心原因是给@AccOmzet和@FietsOmzet赋值时,子查询返回了不止一行结果,但单个变量只能存储一个整数,自然就冲突了。

为啥会返回多行?

看你函数里的子查询,加了GROUP BY h.Huurovereenkomst_Begin_datum, h.Huurovereenkomst_Eind_datum,这会把每一组不同的起止日期都单独计算一次营收,返回多个值。但你要的是整个月份的总营收,不是每组的细分营收,所以这个GROUP BY完全是多余的,反而坑了你。

另外提个小细节:你的fnOmzet函数用了DATEDIFF(Y, @BeginDatum, @EindDatum),这是算年份差啊!如果是按天收租金的话,应该用DATEDIFF(DAY, ...)吧?不然比如租了5天,年份差是0,营收直接变0,这逻辑肯定不对,后面我也会一起修正。

修复后的函数代码

我把两个子查询的GROUP BY去掉,并且把fnOmzet的调用放到SUM里面,确保整个子查询只返回一个总营收值:

CREATE FUNCTION fnOmzetPMaand ( @Maand AS int ) 
RETURNS int 
AS 
BEGIN 
    DECLARE @AccOmzet AS int 
    SET @AccOmzet = ( 
        SELECT SUM(dbo.fnOmzet(a.Accessoire_Dagprijs, h.Huurovereenkomst_Begin_datum, h.Huurovereenkomst_Eind_datum))
        FROM Huurovereenkomst h 
        INNER JOIN HuurovereenkomstAccessoire ha ON ha.HuurovereenkomstAccessoire_Huurovereenkomst_id = h.Huurovereenkomst_id 
        INNER JOIN Accessoire a ON a.Accessoire_id = ha.HuurovereenkomstAccessoire_Accessoire_id 
        WHERE MONTH(h.Huurovereenkomst_Betaal_datum) = @Maand 
    )

    DECLARE @FietsOmzet AS int 
    SET @FietsOmzet = ( 
        SELECT SUM(dbo.fnOmzet(f.Fiets_Dagprijs, h.Huurovereenkomst_Begin_datum, h.Huurovereenkomst_Eind_datum))
        FROM Huurovereenkomst h 
        INNER JOIN HuurovereenkomstFiets hf ON hf.HuurovereenkomstFiets_Huurovereenkomst_id = h.Huurovereenkomst_id 
        INNER JOIN Fiets f ON f.Fiets_id = hf.HuurovereenkomstFiets_Fiets_id 
        WHERE MONTH(h.Huurovereenkomst_Betaal_datum) = @Maand 
    )

    -- 处理NULL情况:如果某个月份没有配件/自行车营收,默认算0
    RETURN ISNULL(@FietsOmzet, 0) + ISNULL(@AccOmzet, 0) 
END

视图也要优化一下

你的原视图会给每条租赁记录都计算一次对应月份的营收,结果会重复出现同一个月份多次。我们按月份分组,只返回每个月份的一次结果:

CREATE VIEW vOmzetPMaand AS 
SELECT 
    DATENAME(MONTH, Huurovereenkomst_Betaal_datum) Maand,
    dbo.fnOmzetPMaand(MONTH(Huurovereenkomst_Betaal_datum)) Omzet
FROM Huurovereenkomst
GROUP BY MONTH(Huurovereenkomst_Betaal_datum), DATENAME(MONTH, Huurovereenkomst_Betaal_datum)
ORDER BY MONTH(Huurovereenkomst_Betaal_datum)

最后修正fnOmzet的逻辑

刚才说的日期差问题,改成按天计算:

ALTER FUNCTION [dbo].[fnOmzet] ( 
    @Bedrag AS int, 
    @BeginDatum AS DATETIME, 
    @EindDatum AS DATETIME 
) RETURNS int 
AS 
BEGIN 
    RETURN @Bedrag * DATEDIFF(DAY, @BeginDatum, @EindDatum)
END

这样运行视图后,就能得到你想要的结果:

May 100
June 200
July 150

内容的提问来源于stack exchange,提问作者MrEmper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:22:11