我有一个表格字段,我们将其称为pattern
,其中包含逗号分隔值列表。
例如:' 10,20,30,40,50'
我需要从所述表中选择*,其中至少有一个来自另一个类似字符串的元素也出现在该字段中。
例如,假设我有字符串' 10,50,70'记录的pattern
字段是' 10,20,30,50,70'应该选择,因为10,50和70出现在' 10,50,70' .`
有没有办法这样做,除了很多OR我检查pattern
LIKE'%10%'或pattern
喜欢%50%或pattern
喜欢%70%?
答案 0 :(得分:0)
您可以使用FIND_IN_SET()
作为替代方案,但如评论中已经建议的那样,请考虑规范化您的表格。
SELECT * FROM table_name
WHERE FIND_IN_SET('10','10,20,30,50,70')
OR FIND_IN_SET('50','10,20,30,50,70')
OR FIND_IN_SET('70','10,20,30,50,70') ;
答案 1 :(得分:0)
如Patrick Hofman所述,规范化数据库是最佳解决方案。
如果你真的必须坚持这样的表格布局,那么有几个解决方案。
您可以拆分逗号分隔值并根据该值加入结果。并非交叉连接表只生成一系列数字(在本例中为0到99),但这必须等于或超过最大分隔值数。它也会很慢,因为没有索引可以使用。此外,还会在内存中生成大量记录以进行此计算。
这样的事情: -
SELECT DISTINCT sub0.id, sub1.id
FROM
(
SELECT DISTINCT id, SUBSTRING_INDEX(SUBSTRING_INDEX(pattern, ',', units.i + tens.i * 10), ',' -1) AS pattern_id
FROM some_table
CROSS JOIN (SELECT 1 AS i UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 0) units
CROSS JOIN (SELECT 1 AS i UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 0) tens
) sub0
INNER JOIN
(
SELECT DISTINCT id, SUBSTRING_INDEX(SUBSTRING_INDEX(pattern, ',', units.i + tens.i * 10), ',' -1) AS pattern_id
FROM some_table
CROSS JOIN (SELECT 1 AS i UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 0) units
CROSS JOIN (SELECT 1 AS i UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 0) tens
) sub1
ON sub0.pattern_id = sub1.pattern_id
AND sub0.id != sub1.id
如果逗号分隔值是另一个表的键,那么你可以根据FIND_IN_SET进行几个连接。
SELECT DISTINCT a.*, b.*
FROM some_table a
INNER JOIN some_patterns b
ON FIND_IN_SET(b.id, a.patterns)
INNER JOIN some_table c
ON FIND_IN_SET(b.id, c.patterns)
实际上,最好对数据库进行规范化,可能使用基于这些解决方案的SQL来帮助您将数据提取到新的规范化格式
答案 2 :(得分:0)
我继承了这种存储小整数列表的方法,并编写了包含的函数,将整数CSV旋转成一列。
CREATE function [dbo].[udf_IntegerColumnFromCSV] ( @DelimStr nvarchar(max) )
returns @ListOfInts table ( Value int )
AS
BEGIN
set @DelimStr = @DelimStr + ',' -- add one more to the end
declare @i int -- the "start" of the next value to be read
declare @j int -- the location of the next comma
declare @le int -- line end
set @i = 1
set @j = 1
set @le = len(@DelimStr)
while ( @j < @le ) begin
set @j = charindex( ',', @DelimStr, @i ) -- find the end of the next row
insert into @ListOfInts (Value) values ( cast(substring( @DelimStr, @i, @j-@i ) as integer) )
set @i = @j + 1
end
return
end
&#13;
如果您将值列表存储为CSV:
从TableX中选择ID,ValueList
ID:ValueList
20:38,39,40,41,42,44,61,62,63,64,65,66,70,71,72
21:12
22:61,62,63,64,65,66
使用该函数将值转换为列:
从TableX中选择ID,vl。*交叉应用dbo.udf_IntegerColumnFromCSV(ValueList)vl
20:38
20:39
20:40
20:41
20:4220:44
20:61
20:62
20:63
20:64
20:65
20:66
20:70
20:71
20:72
21:12
22:61
22:62
22:63
22:64
22:65
22:66