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?

提问人:John Saunders 提问时间:1/6/2011 最后编辑:John Saunders 更新时间:1/19/2011 访问量:1222

问:

我继承了一个存储过程,其代码如下所示。我认为,这有点像穷人的 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)

?

SQL 服务器-2000

评论

1赞 Jimmy 1/6/2011
很高兴看到你对前任的理智有信心。
1赞 Martin Smith 1/6/2011
等价物是,我怀疑没有充分的理由使用这种结构。MAX(CASE index WHEN 123 THEN left([Value],100) ELSE '' END)
0赞 Bill 1/6/2011
过去,我记得 CASE 查询非常慢,尤其是当单个查询中有多个查询时。也许多个 SUBSTRING 和 CONVERT 在某种程度上更快。或?
0赞 OMG Ponies 1/15/2011
穷人的支点?PIVOT 没有得到广泛支持(SQL Server 2005+、Oracle 11g+ - PostgreSQL 还没有见过这样的支持,DB2 可能支持......以上比 PIVOT 更受支持...

答:

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 年有效? 一些提示:

  1. “索引”两边的括号
  2. 缺少案例的“结束”
  3. 缺少 CONVERT(数据似乎不是 varchar,因此需要转换)
  4. 当它不是 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