SQL - 选择字符串元素与另一个字符串元素匹配的位置

时间:2014-11-13 12:28:15

标签: mysql sql csv

我有一个表格字段,我们将其称为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%?

3 个答案:

答案 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;
&#13;
&#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:42

20: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