2

我陷入了僵局。

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

 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

我在'End'附近收到'')'附近的'不正确的语法'

我还收到一个错误,即内部 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)
4

3 回答 3

3

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

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
于 2013-09-30T15:26:18.873 回答
2

)您在案例陈述的末尾有一个额外的内容,请删除它。

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

Seating_Capacity尝试使用表别名访问它l.Seating_Capacity

于 2013-09-30T15:25:13.727 回答
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;

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

我还将您的 ANSI 89 隐式连接转换为 ANSI 92 显式连接,该标准在 20 年内发生了变化,并且有很多充分的理由来切换到更新的语法。但为了完整起见,上述查询的 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  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 来完成。这篇文章中包含了更多相关信息( Aaron Bertrand的另一颗宝石)

于 2013-09-30T15:40:54.280 回答