不使用 EXISTS 嵌套 case 语句引入子查询时,选择列表中只能指定一个表达式
Posted
技术标签:
【中文标题】不使用 EXISTS 嵌套 case 语句引入子查询时,选择列表中只能指定一个表达式【英文标题】:Only one expression can be specified in the select list when the subquery is not introduced with EXISTS nested case statements 【发布时间】:2013-07-31 19:07:11 【问题描述】:我正在尝试创建一个查询,以获取活动在下面打开的小时数是我的查询。我正在使用案例陈述,因为它需要考虑到只计算工作日。这是我的总体目标是实际获得那些日子的时间的过程中的一个步骤。因此,例如,如果这些天的天数超过一个计数并乘以 8.. 如果它小于一个,则执行 datediff 小时并获取当天的小时数.. 任何帮助将不胜感激!
但我收到以下错误:
当不使用 EXISTS 引入子查询时,选择列表中只能指定一个表达式。
DECLARE @workdays int
SELECT creationDateTime,
closedDateTime,DATEDIFF(dd, creationDateTime, closedDateTime)+1,
CASE WHEN (DATEDIFF(dd, creationDateTime, closedDateTime)+1 > 1)
THEN (
SELECT creationDateTime ,closedDateTime,
((DATEDIFF(dd, creationDateTime, closedDateTime)+1)
-(DATEDIFF(wk, creationDateTime, closedDateTime) * 2)
-(CASE WHEN DATENAME(dw, creationDateTime)
= 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, closedDateTime)
= 'Saturday' THEN 1 ELSE 0 END)
)*8 AS workdayhours
FROM table.ofevents where closedDateTime IS NOT NULL) END
FROM table.ofevents where closedDateTime IS NOT NULL
【问题讨论】:
CASE
是一个表达式(不是语句),它只返回一个值。它不能像您在此处尝试使用的那样用于控制流量。
【参考方案1】:
正如错误所说,您不能在一个值中选择多于一列。执行 select 语句时:
SELECT A, B, C ...
每个表达式A
、B
、C
,表示要返回的数据列。该列由具有 integer
或 double
或 varchar
等数据类型的值组成。
所以当你这样做时:
SELECT A, B, (SELECT C, D FROM ...) ...
您是在说“我想要一列 As、一列 Bs 和一列 ...”哎呀。您刚刚破坏了 SQL,因为它不知道如何将多个值放在这样的单个单元格中。 (嗯,一些 SQL 变体确实知道如何做到这一点,但并不总是那么简单。)
你可能想要的是:
SELECT A, B, (SELECT C FROM ...), (SELECT D FROM ...) etc.
所以,意思是这样的:
declare @workdays int
SELECT creationDateTime
, closedDateTime
, DATEDIFF(dd, creationDateTime, closedDateTime)+1
, CASE WHEN (DATEDIFF(dd, creationDateTime, closedDateTime)+1 > 1)
THEN
(SELECT creationDateTime
as workdayhours
from table.ofevents where closedDateTime IS NOT NULL)
END
, CASE WHEN (DATEDIFF(dd, creationDateTime, closedDateTime)+1 > 1)
THEN
(SELECT closedDateTime
as workdayhours
from table.ofevents where closedDateTime IS NOT NULL)
END
, CASE WHEN (DATEDIFF(dd, creationDateTime, closedDateTime)+1 > 1)
THEN ( (DATEDIFF(dd, creationDateTime, closedDateTime)+1 )
-(DATEDIFF(wk, creationDateTime, closedDateTime) * 2)
-(CASE WHEN DATENAME(dw, creationDateTime) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, closedDateTime) = 'Saturday' THEN 1 ELSE 0 END))*8
as workdayhours
from table.ofevents where closedDateTime IS NOT NULL)
END
FROM table.ofevents where closedDateTime IS NOT NULL
看看每个子查询如何只选择一个单个值?
但是,我仍然不明白您为什么需要选择“creationDateTime”和“closeDateTime”,因此您可能可以删除这些列。
最后一条建议,因为我经常在人们的 SQL 相关问题中看到这一点。非常深入、非常彻底地问自己,为什么你想让 SQL 做某事。你为什么输入:
(SELECT creationDateTime ,closedDateTime, ( (DATEDIFF(dd, creationDateTime, closedDateTime)+1 )
为什么creationDateTime
就在closeDateTime
前面,这是什么意思? SQL 是一种声明性语言,您写下您的意图,数据库的工作就是生成与您的意图相匹配的数据。这与大多数命令式编程语言(如 C)不同。在 C 中,您写下如何做某事。对于大多数理解命令式语言的人来说,这使得理解 SQL 变得非常困难。所以,问问自己,为什么你创建了那个子查询,你的目标是什么?
如果我的回答不够,请编辑您的问题以阐明您希望结果查询是什么样子。这是非常重要的。如果你不告诉我们你期望查询返回什么,你怎么能期望告诉数据库,或者期望我们告诉你如何告诉数据库?
【讨论】:
您的查询非常昂贵。它将为结果的每一行多次扫描数据库。 哦,当然。我不确定他们到底为什么要执行他们的子查询。【参考方案2】:我认为您可以摆脱子查询,其他一切都可以工作:
declare @workdays int
SELECT creationDateTime ,closedDateTime,DATEDIFF(dd, creationDateTime, closedDateTime)+1,
CASE WHEN (DATEDIFF(dd, creationDateTime, closedDateTime)+1 > 1)
THEN
(( (DATEDIFF(dd, creationDateTime, closedDateTime)+1 )
-(DATEDIFF(wk, creationDateTime, closedDateTime) * 2)
-(CASE WHEN DATENAME(dw, creationDateTime) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, closedDateTime) = 'Saturday' THEN 1 ELSE 0 END))*8
as workdayhours
END
FROM table.ofevents where closedDateTime IS NOT NULL
我“按原样”保留了您的工作日时间逻辑。
【讨论】:
以上是关于不使用 EXISTS 嵌套 case 语句引入子查询时,选择列表中只能指定一个表达式的主要内容,如果未能解决你的问题,请参考以下文章
不使用 EXISTS 引入子查询时,选择列表中只能指定一个表达式
Select 语句中的 Case 语句中的 Exists 函数需要 FOREVER
带有 Exists 的 WHERE CASE WHEN THEN 语句