我的CASE陈述错了。知道我做错了什么吗?

时间:2013-09-30 15:21:20

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

我在僵局中。

当我运行以下查询时,它可以工作:

 select DISTINCT l.Seating_Capacity - (select count(*)
                        from tblTrainings t1, tbllocations l
                        where l.locationId = t1.LocationId) as
                        availableSeats
                        from tblTrainings t1, tbllocations l
                        where l.locationId = t1.LocationId

但是,我们想添加一个CASE语句,当Seating_Capacity - 如上所示的总计数= 0时,显示'FULL'消息。

否则,显示剩余号码。

以下是该查询:

                 select DISTINCT case when l.Seating_Capacity - (select count(*)
                from tblTrainings t1, tbllocations l
                where l.locationId = t1.LocationId) = 0 then 'full' else STR(Seating_Capacity) end)
                availableSeats
                from tblTrainings t1, tbllocations l
                where l.locationId = t1.LocationId

我收到'不正确的语法''''接近'结束'

我也收到一条错误,内部Seating_Capacity是无效的列名。

非常感谢您的协助。

我一定是在梦乡,因为我认为它在测试过程中起作用了。

现在,该应用程序已启用,但无效。

提前多多感谢

select DISTINCT l.LocationId,c.courseId, c.coursename, l.Seating_Capacity - (select count(*)
                        from tblTrainings t1
                        where l.locationId = t1.LocationId and c.courseId = t1.courseId) as
                        availableSeats,d.dateid,d.trainingDates,d.trainingtime,c.CourseDescription,
                        i.instructorName,l.location,l.seating_capacity 
                        from tblLocations l
                        Inner Join tblCourses c on l.locationId = c.locationId
                        left join tblTrainings t on l.locationId = t.LocationId and c.courseId = t.courseId
                        Inner Join tblTrainingDates d on c.dateid=d.dateid 
                        Inner Join tblCourseInstructor ic on c.courseId = ic.CourseId  
                        Inner Join tblInstructors i on ic.instructorId = i.instructorId
                        WHERE CONVERT(VARCHAR(10), d.trainingDates, 101) >= CONVERT(VARCHAR(10), GETDATE(), 101)

3 个答案:

答案 0 :(得分:3)

为避免重复表达,您可以使用WITH clause来简化查询:

WITH (
   -- Start with your query that already works
   SELECT DISTINCT l.Seating_Capacity - (select count(*)
                    from tblTrainings t1, tbllocations l
                    where l.locationId = t1.LocationId) AS availableSeats
   FROM tblTrainings t1, tbllocations l
   WHERE l.locationId = t1.LocationId
) AS source
SELECT
    -- Add a CASE statement on top of it
    CASE WHEN availableSeats = 0 THEN 'Full'
    ELSE STR(availableSeats)
    END AS availableSeats
FROM source

答案 1 :(得分:2)

在您的案例陈述结尾处有一个额外的)删除它。

 0 then 'full' else STR(Seating_Capacity) end)
                                            ^^^

Seating_Capacity尝试使用{al} {/ p>等表别名访问它

答案 2 :(得分:0)

我认为你的子查询使查询复杂化了。据我所知,以下内容应该可以根据需要使用:

SELECT  AvailableSeats = CASE WHEN l.Seating_Capacity - COUNT(*) = 0 THEN 'Full' 
                            ELSE STR(l.Seating_Capacity - COUNT(*)) 
                        END
FROM    tblTrainings t1
        INNER JOIN tblLocations l
            ON l.LocationID = t1.LocationID
GROUP BY l.Seating_Capacity;

我已将其他人更改为STR(l.Seating_Capacity - COUNT(*)),因为我认为您想知道剩下的座位,而不仅仅是容量?如果我误解了要求,只需将其更改为STR(l.Seating_Capacity)

我还将ANSI 89隐式连接切换为ANSI 92显式连接,标准更改超过20年,并且plenty of good reasons可以切换到更新的语法。但为了完整起见,上述查询的ANSI 89版本将是:

SELECT  AvailableSeats = CASE WHEN l.Seating_Capacity - COUNT(*) = 0 THEN 'Full' 
                            ELSE STR(l.Seating_Capacity - COUNT(*)) 
                        END
FROM    tblTrainings t1, tblLocations l
WHERE   l.LocationID = t1.LocationID
GROUP BY l.Seating_Capacity;

修改

要调整完整查询,您只需使用已连接的子查询替换select中的子查询:

SELECT  l.LocationId,
        c.courseId, 
        c.coursename, 
        CASE WHEN l.Seating_Capacity - t.SeatsTaken = 0 THEN 'Full' 
            ELSE STR(l.Seating_Capacity - t.SeatsTaken) 
            END AS availableSeats,
        d.dateid,
        d.trainingDates,
        d.trainingtime,
        c.CourseDescription,
        i.instructorName,
        l.location,
        l.seating_capacity 
FROM    tblLocations l
        INNER JOIN tblCourses c 
            ON l.locationId = c.locationId
        LEFT JOIN 
        (   SELECT  t.LocationID, t.CourseID, SeatsTaken = COUNT(*)
            FROM    tblTrainings t 
            GROUP BY t.LocationID, t.CourseID
        ) t
            ON l.locationId = t.LocationId 
            AND c.courseId = t.courseId
        INNER JOIN tblTrainingDates d 
            ON c.dateid=d.dateid 
        INNER JOIN tblCourseInstructor ic 
            ON c.courseId = ic.CourseId  
        INNER JOIN tblInstructors i 
            ON ic.instructorId = i.instructorId
WHERE   d.trainingDates >= CAST(GETDATE() AS DATE);

JOIN倾向于比相关子查询更好地优化(尽管有时优化器可以确定JOIN会起作用),这也意味着您可以多次引用结果(SeatsTaken)而无需重新评估子查询

此外,通过将计数移至子查询,并将联接移至tblTrainings,我认为您无需DISTINCT来提高性能。

最后我改变了这一行:

WHERE CONVERT(VARCHAR(10), d.trainingDates, 101) >= CONVERT(VARCHAR(10), GETDATE(), 101)

WHERE   d.trainingDates >= CAST(GETDATE() AS DATE);

我不知道你是否这样做,但如果你有一个关于d.TrainingDates的索引,那么通过将其转换为varchar来与今天进行比较,你将删除优化器使用这个索引的能力,因为你只是说今天午夜>=,无需在d.TrainingDates上执行任何转换,您需要做的就是删除GETDATE()的时间部分,这可以通过强制转换为DATE来完成。关于此的更多内容包含in this article(来自Aaron Bertrand的另一个宝石)