如何避免 SELECT、GROUP BY 和 ORDER BY 中的函数重复 SQL
How to avoid function repetition in SELECT, GROUP BY, and ORDER BY in SQL
我正在编写一个统计查询,其中值在 SELECT
、GROUP BY
和 ORDER BY
中重复。必须重复相同的值使得难以读取和修改查询。
如何避免在下面的查询中重复 FLOOR(COALESCE(LEN(Body), 0) / 100)
3-4 次。
SELECT FLOOR(COALESCE(LEN(Body), 0) / 100) * 100 as BodyLengthStart,
(FLOOR(COALESCE(LEN(Body), 0) / 100) + 1) * 100 - 1 as BodyLengthEnd,
COUNT(*) as MessageCount
FROM [Message]
GROUP BY FLOOR(COALESCE(LEN(Body), 0) / 100)
ORDER BY FLOOR(COALESCE(LEN(Body), 0) / 100)
查询的输出是消息的数量与它们有多少个字符相结合。
BodyLengthStart
BodyLengthEnd
MessageCount
0
99
130
100
199
76
200
299
36
您可以使用常见的 table 表达式:
WITH cte AS
(
SELECT FLOOR(COALESCE(LEN(Body), 0) / 100) * 100 as BodyLengthStart,
(FLOOR(COALESCE(LEN(Body), 0) / 100) + 1) * 100 - 1 as BodyLengthEnd
FROM [Message]
)
SELECT BodyLengthStart,BodyLengthEnd,COUNT(*)
FROM cte
GROUP BY BodyLengthStart,BodyLengthEnd
使用子select:
SELECT BodyLengthStart,
BodyLengthEnd,
COUNT(*)
FROM (SELECT FLOOR(COALESCE(LEN(Body), 0) / 100) * 100 as BodyLengthStart,
(FLOOR(COALESCE(LEN(Body), 0) / 100) + 1) * 100 - 1 as BodyLengthEnd
FROM [Message]) as a
GROUP BY BodyLengthStart,
BodyLengthEnd
可以在FROM
之后定义一个SELECT
;这样,您就可以事先详细说明您的数据。
一个选项可能是 CTE(通用 Table 表达式),大致如下:
WITH x AS
(
SELECT FLOOR(COALESCE(LEN(Body), 0) / 100) AS BodyLength
FROM [Message]
)
SELECT BodyLength * 100 AS BodyLengthStart,
(BodyLength + 1) * 100 - 1 AS BodyLengthEnd,
COUNT(*) as MessageCount
FROM x
GROUP BY BodyLength
ORDER BY BodyLength
附带说明 - 如果在此之前的语句没有以分号 (;) 结尾,则这将无法按预期工作。
使用交叉应用
SELECT BodyLengthStart,
BodyLengthEnd,
COUNT(*)
FROM [Message]
CROSS APPLY (
VALUES
(FLOOR(COALESCE(LEN(Body), 0) / 100))
) a1(v)
CROSS APPLY (
VALUES
(v * 100, (v + 1) * 100 - 1)
) a2(BodyLengthStart, BodyLengthEnd)
GROUP BY BodyLengthStart,
BodyLengthEnd
我正在编写一个统计查询,其中值在 SELECT
、GROUP BY
和 ORDER BY
中重复。必须重复相同的值使得难以读取和修改查询。
如何避免在下面的查询中重复 FLOOR(COALESCE(LEN(Body), 0) / 100)
3-4 次。
SELECT FLOOR(COALESCE(LEN(Body), 0) / 100) * 100 as BodyLengthStart,
(FLOOR(COALESCE(LEN(Body), 0) / 100) + 1) * 100 - 1 as BodyLengthEnd,
COUNT(*) as MessageCount
FROM [Message]
GROUP BY FLOOR(COALESCE(LEN(Body), 0) / 100)
ORDER BY FLOOR(COALESCE(LEN(Body), 0) / 100)
查询的输出是消息的数量与它们有多少个字符相结合。
BodyLengthStart | BodyLengthEnd | MessageCount |
---|---|---|
0 | 99 | 130 |
100 | 199 | 76 |
200 | 299 | 36 |
您可以使用常见的 table 表达式:
WITH cte AS
(
SELECT FLOOR(COALESCE(LEN(Body), 0) / 100) * 100 as BodyLengthStart,
(FLOOR(COALESCE(LEN(Body), 0) / 100) + 1) * 100 - 1 as BodyLengthEnd
FROM [Message]
)
SELECT BodyLengthStart,BodyLengthEnd,COUNT(*)
FROM cte
GROUP BY BodyLengthStart,BodyLengthEnd
使用子select:
SELECT BodyLengthStart,
BodyLengthEnd,
COUNT(*)
FROM (SELECT FLOOR(COALESCE(LEN(Body), 0) / 100) * 100 as BodyLengthStart,
(FLOOR(COALESCE(LEN(Body), 0) / 100) + 1) * 100 - 1 as BodyLengthEnd
FROM [Message]) as a
GROUP BY BodyLengthStart,
BodyLengthEnd
可以在FROM
之后定义一个SELECT
;这样,您就可以事先详细说明您的数据。
一个选项可能是 CTE(通用 Table 表达式),大致如下:
WITH x AS
(
SELECT FLOOR(COALESCE(LEN(Body), 0) / 100) AS BodyLength
FROM [Message]
)
SELECT BodyLength * 100 AS BodyLengthStart,
(BodyLength + 1) * 100 - 1 AS BodyLengthEnd,
COUNT(*) as MessageCount
FROM x
GROUP BY BodyLength
ORDER BY BodyLength
附带说明 - 如果在此之前的语句没有以分号 (;) 结尾,则这将无法按预期工作。
使用交叉应用
SELECT BodyLengthStart,
BodyLengthEnd,
COUNT(*)
FROM [Message]
CROSS APPLY (
VALUES
(FLOOR(COALESCE(LEN(Body), 0) / 100))
) a1(v)
CROSS APPLY (
VALUES
(v * 100, (v + 1) * 100 - 1)
) a2(BodyLengthStart, BodyLengthEnd)
GROUP BY BodyLengthStart,
BodyLengthEnd