提问人:John Saunders 提问时间:1/6/2011 最后编辑:John Saunders 更新时间:1/19/2011 访问量:1222
SQL中“MAX(SUBSTRING(CONVERT(X),1,DATALENGTH(CONVERT(X))*1 or 0))”的目的是什么?
What's the Purpose of "MAX(SUBSTRING(CONVERT(X),1,DATALENGTH(CONVERT(X))*1 or 0))" in SQL?
问:
我继承了一个存储过程,其代码如下所示。我认为,这有点像穷人的 PIVOT(必须在 SQL Server 2000 上运行)。
SELECT
[TheDate] = MAX(
substring(
CONVERT(VarChar(100), thedate, 101),
1,
datalength(CONVERT(VarChar(100), thedate, 101)) *
( CASE index WHEN 123 THEN 1 ELSE 0 END ))),
[Scaled] = MAX(
substring(
CONVERT(VarChar(100), Scaled),
1,
datalength(CONVERT(VarChar(100), Scaled)) *
( CASE index WHEN 123 THEN 1 ELSE 0 END ))),
[Value] = MAX(
substring(
CONVERT(VarChar(100), [Value]),
1,
datalength(CONVERT(VarChar(100), [Value])) *
( CASE index WHEN 123 THEN 1 ELSE 0 END ))),
-- Repeat for other values of "index"
GROUP BY other columns
以前有人见过这种结构吗?不是“枢轴”的东西,而是
MAX(SUBSTRING(CONVERT(X),1,DATALENGTH(CONVERT(X))*1 or 0))
为什么不直接使用
MAX(CASE index WHEN 123 THEN [Value] ELSE NULL END)
?
答:
1赞
RichardTheKiwi
1/15/2011
#1
有趣的报价
这有点像穷人的支点
我碰巧知道 PIVOT 算子是皇帝在多个 CASE 语句之上的新衣服。事实上,这就是查询计划的显示方式。因此,看待它的方式不止一种。
Martin 使用 LEFT(, length) 是转换为特定长度的快捷方式,因为 LEFT(和 RIGHT)隐式转换第一个参数。但是,在一种情况下,对于特定格式的 CONVERT(varchar, date, 101),它不起作用。
DATALENGTH(CONVERT(X))*1 或 0)
这可能是尝试根据列中的最大长度来调整结果列的大小,但显然这不是正确的代码(如果这是目的的话)。
MAX(CASE index WHEN 123 THEN [Value] ELSE NULL)
看起来好多了。“index”是一个关键字,所以如果你从工作代码中复制你的代码片段,我会感到惊讶。也许它在 2000 年有效? 一些提示:
- “索引”两边的括号
- 缺少案例的“结束”
- 缺少 CONVERT(数据似乎不是 varchar,因此需要转换)
当它不是 123 时,原始返回 '' 而不是 NULL
MAX(CASE [index] WHEN 123 THEN CONVERT(varchar(100), [Value], 101) ELSE '' END)
(我输入了 101 以使 [value] 与日期格式一致。它对数字没有影响)
评论
0赞
OMG Ponies
1/15/2011
上次测试时,我的 PIVOT 语句比 aggregate/CASE 等效语句慢一秒。
0赞
RichardTheKiwi
1/15/2011
@OMG - AFAIK,它在内部优化为相同的计划,因此除非您在查询中引入了一些细微差别,否则它们应该会出现相同的情况。然而,在所有测试中,至少有 10 个其他因素在起作用(磁盘 I/O、内存、缓冲区、计划缓存、掷骰子等),所以只要“秒”在一定的误差范围内,我就会忽略它。
0赞
John Saunders
1/19/2011
@cyberwiki:“索引”是一个用于混淆的词。您可能认为转换是原因之一,这是对的。基础表已更改。新表更加“类型安全”。例如,日期/时间实际上是 ,而它们在原版中只是 varchar。也许其中一些是原始表实际上需要的。datetime
评论
MAX(CASE index WHEN 123 THEN left([Value],100) ELSE '' END)