检查varchar中的字符
check chars in varchar
如何检查 varchar 是否包含来自另一个 varchar 的所有字符,其中字符序列无关紧要?
例如:我在 table 'Table'
中有 varchar @a = 'ABC'
和列 'Col'
,其中行 'Col' = 'CBAD'
。我想要 select 这一行,因为它包含来自 @a
变量的所有字符。请大家帮忙。
我试过类似的东西:
DECLARE @a varchar(5) = 'ABCD'
DECLARE @b varchar(5) = 'DCA'
DECLARE @i int = 0
DECLARE @pat varchar(30) = ''
while @i <> len(@b) BEGIN
SET @i = @i + 1
SET @pat = @pat + '[' + @a + ']'
END
SELECT @pat
IF @b LIKE @pat SELECT 1
ELSE SELECT 0
但是我不能把这个放到WHERE
条件下
你可以这样试试:
SELECT * FROM yourTable where colname like '%[A]%'
AND colname like '%[B]%'
AND colname like '%[C]%'
或者您可以尝试使用 PATINDEX
SELECT * FROM yourTable WHERE PATINDEX('%[ABC]%',colname) > 1
您首先需要将要检查的变量拆分成行,并删除重复项。对于只有几个字符,您可以简单地使用 table 值构造函数:
DECLARE @b varchar(5) = 'DCA';
SELECT DISTINCT Letter = SUBSTRING(@b, n.Number, 1)
FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) AS n (Number)
WHERE n.Number <= LEN(@b)
给出:
Letter
----------
D
C
A
现在您可以将它与您的列进行比较,并将其限制为仅包含所有字母的列(在 HAVING
子句中完成)
DECLARE @b varchar(5) = 'DCA';
WITH Letters AS
( SELECT DISTINCT Letter = SUBSTRING(@b, n.Number, 1)
FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) AS n (Number)
WHERE n.Number <= LEN(@b)
)
SELECT *
FROM (VALUES ('AA'), ('ABCD'), ('ABCDEFG'), ('CAB'), ('NA')) AS t (Col)
WHERE EXISTS
( SELECT 1
FROM Letters AS l
WHERE t.Col LIKE '%' + l.Letter + '%'
HAVING COUNT(DISTINCT l.Letter) = (SELECT COUNT(*) FROM Letters)
);
如果您的变量可以超过 10 个字符,那么您可能需要采用稍微不同的字符串拆分方法。我仍然会使用数字来执行此操作,但会使用 Itzik Ben-Gan's stacked CTE method:
WITH N1 AS (SELECT N FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS n (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2)
SELECT ROW_NUMBER() OVER(ORDER BY N)
FROM N3;
这将为您提供一组从 1 到 10,000 的数字,您可以根据需要简单地添加更多 CTE 和交叉连接以扩展该过程。所以使用更长的字符串你可能有:
DECLARE @b varchar(5) = 'DCAFGHIJKLMNEOPNFEDACCRADFAE';
WITH N1 AS (SELECT N FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS n (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2),
Numbers (Number) AS (SELECT TOP (LEN(@b)) ROW_NUMBER() OVER(ORDER BY N) FROM N3),
Letters AS (SELECT DISTINCT Letter = SUBSTRING(@b, n.Number, 1) FROM Numbers AS n)
SELECT *
FROM (VALUES ('ABCDDCAFGHIJKLMNEOPNFEDACCRADFAEEFG'), ('CAB'), ('NA')) AS t (Col)
WHERE EXISTS
( SELECT 1
FROM Letters AS l
WHERE t.Col LIKE '%' + l.Letter + '%'
HAVING COUNT(DISTINCT l.Letter) = (SELECT COUNT(*) FROM Letters)
);
还有一个版本:
DECLARE @a varchar(5) = 'ABCD'
DECLARE @b varchar(5) = 'DCA'
;WITH cte AS(
SELECT ROW_NUMBER() OVER( ORDER BY (SELECT NULL)) rn
FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) a(n)
CROSS JOIN (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) b(n)
),
astring AS(SELECT DISTINCT SUBSTRING(@a, rn, 1) AS l FROM cte WHERE rn <= LEN(@a)),
bstring AS(SELECT DISTINCT SUBSTRING(@b, rn, 1) AS l FROM cte WHERE rn <= LEN(@b))
SELECT CASE WHEN EXISTS(SELECT * FROM bstring WHERE l NOT IN(SELECT * FROM astring))
THEN 0 ELSE 1
END AS result
SELECT * FROM yourTable WHERE PATINDEX('%A%',colname) >= 1 and PATINDEX('%B%',colname) >= 1 AND PATINDEX('%C%',colname) >= 1
如何检查 varchar 是否包含来自另一个 varchar 的所有字符,其中字符序列无关紧要?
例如:我在 table 'Table'
中有 varchar @a = 'ABC'
和列 'Col'
,其中行 'Col' = 'CBAD'
。我想要 select 这一行,因为它包含来自 @a
变量的所有字符。请大家帮忙。
我试过类似的东西:
DECLARE @a varchar(5) = 'ABCD'
DECLARE @b varchar(5) = 'DCA'
DECLARE @i int = 0
DECLARE @pat varchar(30) = ''
while @i <> len(@b) BEGIN
SET @i = @i + 1
SET @pat = @pat + '[' + @a + ']'
END
SELECT @pat
IF @b LIKE @pat SELECT 1
ELSE SELECT 0
但是我不能把这个放到WHERE
条件下
你可以这样试试:
SELECT * FROM yourTable where colname like '%[A]%'
AND colname like '%[B]%'
AND colname like '%[C]%'
或者您可以尝试使用 PATINDEX
SELECT * FROM yourTable WHERE PATINDEX('%[ABC]%',colname) > 1
您首先需要将要检查的变量拆分成行,并删除重复项。对于只有几个字符,您可以简单地使用 table 值构造函数:
DECLARE @b varchar(5) = 'DCA';
SELECT DISTINCT Letter = SUBSTRING(@b, n.Number, 1)
FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) AS n (Number)
WHERE n.Number <= LEN(@b)
给出:
Letter
----------
D
C
A
现在您可以将它与您的列进行比较,并将其限制为仅包含所有字母的列(在 HAVING
子句中完成)
DECLARE @b varchar(5) = 'DCA';
WITH Letters AS
( SELECT DISTINCT Letter = SUBSTRING(@b, n.Number, 1)
FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) AS n (Number)
WHERE n.Number <= LEN(@b)
)
SELECT *
FROM (VALUES ('AA'), ('ABCD'), ('ABCDEFG'), ('CAB'), ('NA')) AS t (Col)
WHERE EXISTS
( SELECT 1
FROM Letters AS l
WHERE t.Col LIKE '%' + l.Letter + '%'
HAVING COUNT(DISTINCT l.Letter) = (SELECT COUNT(*) FROM Letters)
);
如果您的变量可以超过 10 个字符,那么您可能需要采用稍微不同的字符串拆分方法。我仍然会使用数字来执行此操作,但会使用 Itzik Ben-Gan's stacked CTE method:
WITH N1 AS (SELECT N FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS n (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2)
SELECT ROW_NUMBER() OVER(ORDER BY N)
FROM N3;
这将为您提供一组从 1 到 10,000 的数字,您可以根据需要简单地添加更多 CTE 和交叉连接以扩展该过程。所以使用更长的字符串你可能有:
DECLARE @b varchar(5) = 'DCAFGHIJKLMNEOPNFEDACCRADFAE';
WITH N1 AS (SELECT N FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS n (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2),
Numbers (Number) AS (SELECT TOP (LEN(@b)) ROW_NUMBER() OVER(ORDER BY N) FROM N3),
Letters AS (SELECT DISTINCT Letter = SUBSTRING(@b, n.Number, 1) FROM Numbers AS n)
SELECT *
FROM (VALUES ('ABCDDCAFGHIJKLMNEOPNFEDACCRADFAEEFG'), ('CAB'), ('NA')) AS t (Col)
WHERE EXISTS
( SELECT 1
FROM Letters AS l
WHERE t.Col LIKE '%' + l.Letter + '%'
HAVING COUNT(DISTINCT l.Letter) = (SELECT COUNT(*) FROM Letters)
);
还有一个版本:
DECLARE @a varchar(5) = 'ABCD'
DECLARE @b varchar(5) = 'DCA'
;WITH cte AS(
SELECT ROW_NUMBER() OVER( ORDER BY (SELECT NULL)) rn
FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) a(n)
CROSS JOIN (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) b(n)
),
astring AS(SELECT DISTINCT SUBSTRING(@a, rn, 1) AS l FROM cte WHERE rn <= LEN(@a)),
bstring AS(SELECT DISTINCT SUBSTRING(@b, rn, 1) AS l FROM cte WHERE rn <= LEN(@b))
SELECT CASE WHEN EXISTS(SELECT * FROM bstring WHERE l NOT IN(SELECT * FROM astring))
THEN 0 ELSE 1
END AS result
SELECT * FROM yourTable WHERE PATINDEX('%A%',colname) >= 1 and PATINDEX('%B%',colname) >= 1 AND PATINDEX('%C%',colname) >= 1