我如何检查varchar是否包含来自另一个varchar的所有字符,其中字符序列是无关紧要的?
例如:我在表’Table’中有varchar @a =’ABC’和列’Col’在哪里是’Col’=’CBAD’的行.我想选择这个行,因为它包含@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条件下
解决方法
您首先需要将要检查的变量拆分成行,并删除重复项.只有几个字符,你可以简单地使用一个表值构造函数:
- 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,1)
- FROM (VALUES(1),(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)) 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),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,1) FROM Numbers AS n)
- SELECT *
- FROM (VALUES ('ABCDDCAFGHIJKLMNEOPNFEDACCRADFAEEFG'),('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)
- );