如何查询范围在 SQL 中的基于 SQL 的集合
How to query number based SQL Sets with Ranges in SQL
我正在寻找的是在 MSSQL 中创建包含一组值的复杂 IN 或 LIKE 子句的方法,其中一些值将是范围。
有点像这样,有一些单一的数字,也有一些数字范围。
EX: SELECT * FROM table WHERE 字段 LIKE/IN '1-10, 13, 24, 51-60'
我需要找到一种方法来执行此操作,而不必分别指定范围内的每个数字,也不必说“字段类似废话或字段介于废话和废话之间或字段类似废话。
这只是一个简单的示例,但真正的查询将包含许多组和大范围,因此所有 OR 都不起作用。
一个相当简单的方法是用你的 values/ranges:
加载临时文件 table
CREATE TABLE #Ranges (ValA int, ValB int)
INSERT INTO #Ranges
VALUES
(1, 10)
,(13, NULL)
,(24, NULL)
,(51,60)
SELECT *
FROM Table t
JOIN #Ranges R
ON (t.Field = R.ValA AND R.ValB IS NULL)
OR (t.Field BETWEEN R.ValA and R.ValB AND R.ValB IS NOT NULL)
不过,BETWEEN
不会很好地扩展,因此您可能需要考虑扩展它以包括所有值并消除范围。
你可以用 CTE 做到这一点。
首先,创建一个 numbers/tally table 如果您还没有一个(如果您要经常使用它,最好让它永久而不是临时的):
;WITH Numbers AS
(
SELECT
1 as Value
UNION ALL
SELECT
Numbers.Value + 1
FROM
Numbers
)
SELECT TOP 1000
Value
INTO ##Numbers
FROM
Numbers
OPTION (MAXRECURSION 1000)
然后您可以使用 CTE 来解析逗号分隔的字符串并将范围与数字 table 连接起来以获得包含您要查找的整个数字列表的 "NewValue" 列:
DECLARE @TestData varchar(50) = '1-10,13,24,51-60'
;WITH CTE AS
(
SELECT
1 AS RowCounter,
1 AS StartPosition,
CHARINDEX(',',@TestData) AS EndPosition
UNION ALL
SELECT
CTE.RowCounter + 1,
EndPosition + 1,
CHARINDEX(',',@TestData, CTE.EndPosition+1)
FROM CTE
WHERE
CTE.EndPosition > 0
)
SELECT
u.Value,
u.StartValue,
u.EndValue,
n.Value as NewValue
FROM
(
SELECT
Value,
SUBSTRING(Value,1,CASE WHEN CHARINDEX('-',Value) > 0 THEN CHARINDEX('-',Value)-1 ELSE LEN(Value) END) AS StartValue,
SUBSTRING(Value,CASE WHEN CHARINDEX('-',Value) > 0 THEN CHARINDEX('-',Value)+1 ELSE 1 END,LEN(Value)- CHARINDEX('-',Value)) AS EndValue
FROM
(
SELECT
SUBSTRING(@TestData, StartPosition, CASE WHEN EndPosition > 0 THEN EndPosition-StartPosition ELSE LEN(@TestData)-StartPosition+1 END) AS Value
FROM
CTE
)t
)u INNER JOIN ##Numbers n ON n.Value BETWEEN u.StartValue AND u.EndValue
你需要做的就是使用 IN 语句查询结果,比如
SELECT * FROM MyTable WHERE Value IN (SELECT NewValue FROM (/*subquery from above*/)t)
我正在寻找的是在 MSSQL 中创建包含一组值的复杂 IN 或 LIKE 子句的方法,其中一些值将是范围。
有点像这样,有一些单一的数字,也有一些数字范围。
EX: SELECT * FROM table WHERE 字段 LIKE/IN '1-10, 13, 24, 51-60'
我需要找到一种方法来执行此操作,而不必分别指定范围内的每个数字,也不必说“字段类似废话或字段介于废话和废话之间或字段类似废话。 这只是一个简单的示例,但真正的查询将包含许多组和大范围,因此所有 OR 都不起作用。
一个相当简单的方法是用你的 values/ranges:
加载临时文件 tableCREATE TABLE #Ranges (ValA int, ValB int)
INSERT INTO #Ranges
VALUES
(1, 10)
,(13, NULL)
,(24, NULL)
,(51,60)
SELECT *
FROM Table t
JOIN #Ranges R
ON (t.Field = R.ValA AND R.ValB IS NULL)
OR (t.Field BETWEEN R.ValA and R.ValB AND R.ValB IS NOT NULL)
不过,BETWEEN
不会很好地扩展,因此您可能需要考虑扩展它以包括所有值并消除范围。
你可以用 CTE 做到这一点。
首先,创建一个 numbers/tally table 如果您还没有一个(如果您要经常使用它,最好让它永久而不是临时的):
;WITH Numbers AS
(
SELECT
1 as Value
UNION ALL
SELECT
Numbers.Value + 1
FROM
Numbers
)
SELECT TOP 1000
Value
INTO ##Numbers
FROM
Numbers
OPTION (MAXRECURSION 1000)
然后您可以使用 CTE 来解析逗号分隔的字符串并将范围与数字 table 连接起来以获得包含您要查找的整个数字列表的 "NewValue" 列:
DECLARE @TestData varchar(50) = '1-10,13,24,51-60'
;WITH CTE AS
(
SELECT
1 AS RowCounter,
1 AS StartPosition,
CHARINDEX(',',@TestData) AS EndPosition
UNION ALL
SELECT
CTE.RowCounter + 1,
EndPosition + 1,
CHARINDEX(',',@TestData, CTE.EndPosition+1)
FROM CTE
WHERE
CTE.EndPosition > 0
)
SELECT
u.Value,
u.StartValue,
u.EndValue,
n.Value as NewValue
FROM
(
SELECT
Value,
SUBSTRING(Value,1,CASE WHEN CHARINDEX('-',Value) > 0 THEN CHARINDEX('-',Value)-1 ELSE LEN(Value) END) AS StartValue,
SUBSTRING(Value,CASE WHEN CHARINDEX('-',Value) > 0 THEN CHARINDEX('-',Value)+1 ELSE 1 END,LEN(Value)- CHARINDEX('-',Value)) AS EndValue
FROM
(
SELECT
SUBSTRING(@TestData, StartPosition, CASE WHEN EndPosition > 0 THEN EndPosition-StartPosition ELSE LEN(@TestData)-StartPosition+1 END) AS Value
FROM
CTE
)t
)u INNER JOIN ##Numbers n ON n.Value BETWEEN u.StartValue AND u.EndValue
你需要做的就是使用 IN 语句查询结果,比如
SELECT * FROM MyTable WHERE Value IN (SELECT NewValue FROM (/*subquery from above*/)t)