CASE语句为标量变量返回多行

时间:2012-08-08 13:04:25

标签: sql sql-server

我有以下代码

  DECLARE @ProjectID INT
    DECLARE @getSLAPrjectID CURSOR
    SET @getSLAPrjectID = CURSOR FOR SELECT ProjectID FROM SLA

    OPEN @getSLAPrjectID

    FETCH NEXT
    FROM @getSLAPrjectID INTO @ProjectID
    WHILE @@FETCH_STATUS = 0
    BEGIN

    BEGIN

    SET @ScheduleVariance = (select case when (DATEDIFF(day,PlannedStartDate,PlannedEndDate)=0) THEN 0 ELSE (DATEDIFF(day,ActualStartDate,ActualEndDate)-DATEDIFF(day,PlannedStartDate,PlannedEndDate))/CAST(DATEDIFF(day,PlannedStartDate,PlannedEndDate) as float) END from SLA)

    -- other piece of code that is working fine

    END

    FETCH NEXT
    FROM @getSLAPrjectID INTO @ProjectID

    END

    CLOSE @getSLAPrjectID
    DEALLOCATE @getSLAPrjectID

    --end

我收到以下错误:子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。

如果这段代码中的CASE语句或标量变量的替代方法有替代方法,请告诉我。

4 个答案:

答案 0 :(得分:1)

请尝试在子查询中使用where条件SLA.ProjectID = @ProjectID。

SET @ScheduleVariance = (select case when (DATEDIFF(day,PlannedStartDate,PlannedEndDate)=0) THEN 0 ELSE (DATEDIFF(day,ActualStartDate,ActualEndDate)-DATEDIFF(day,PlannedStartDate,PlannedEndDate))/CAST(DATEDIFF(day,PlannedStartDate,PlannedEndDate) as float) END from SLA where SLA.ProjectID = @ProjectID)

答案 1 :(得分:0)

很可能是因为表SLA包含多行。要解决它,您应该添加一个WHERE子句,将结果缩小到一行。

我强烈建议使用TOP 1,除非您完全确定行集的第一行(正确排序)是您正在寻找的行。

答案 2 :(得分:0)

显然这一行返回的行多于一行:

SET @ScheduleVariance = (select case when (DATEDIFF(day,PlannedStartDate,PlannedEndDate)=0)
                                     THEN 0
                                     ELSE (DATEDIFF(day,ActualStartDate,ActualEndDate)-DATEDIFF(day,PlannedStartDate,PlannedEndDate))/CAST(DATEDIFF(day,PlannedStartDate,PlannedEndDate) as float)
                         END from SLA)

您需要以下其中一项来获取一行:WHERE子句,聚合函数(WHERE?)或TOP 1.

答案 3 :(得分:0)

SLA中有一行以上。只要您使用TOP 1,就可以使用ORDER BY来解决此问题,以确保查询具有确定性。

SELECT  TOP 1 @ScheduleVariance = CASE WHEN (DATEDIFF(DAY, PlannedStartDate,PlannedEndDate) = 0) THEN 0 
                                ELSE (DATEDIFF(DAY, ActualStartDate, ActualEndDate) / CAST(DATEDIFF(DAY,PlannedStartDate, PlannedEndDate) AS FLOAT)) - 1 
                            END 
FROM    SLA
ORDER BY ProjectID

但是,我怀疑你也缺少查询中的where子句。

SELECT  @ScheduleVariance = CASE WHEN (DATEDIFF(DAY, PlannedStartDate,PlannedEndDate) = 0) THEN 0 
                                ELSE (DATEDIFF(DAY, ActualStartDate, ActualEndDate) / CAST(DATEDIFF(DAY,PlannedStartDate, PlannedEndDate) AS FLOAT)) - 1 
                            END 
FROM    SLA
WHERE   ProjectID = @ProjectID

SET @ScheduleVariance = 
    (   SELECT  CASE WHEN (DATEDIFF(day,PlannedStartDate,PlannedEndDate) = 0) THEN 0 
                    ELSE (DATEDIFF(day, ActualStartDate, ActualEndDate) / CAST(DATEDIFF(DAY,PlannedStartDate, PlannedEndDate) AS FLOAT)) - 1 
                END 
        FROM    SLA
        WHERE   ProjectID = @ProjectID
    )

注意,我还整理了你的计算,所以改了

(x - y) / y 

(x / y) - 1