【问题标题】:SQL - select where elements of a string match elements of another stringSQL - 选择一个字符串的元素匹配另一个字符串的元素
【发布时间】:2015-01-10 14:23:08
【问题描述】:

我有一个表格字段,我们称之为pattern,其中包含一个逗号分隔值列表。 例如:'10,20,30,40,50'

我需要从所述表中选择 *,其中至少一个来自另一个类似字符串的元素也出现在该字段中。

例如,假设我有字符串 '10,50,70' 应该选择 pattern 字段为 '10,20,30,50,70' 的记录,因为 '10 中存在 10 和 70 ,50,70'。`

有什么方法可以做到这一点,除了很多 OR 我检查 pattern LIKE '%10%' OR pattern LIKE %50% OR pattern LIKE %70% 吗?

【问题讨论】:

  • 阅读数据库规范化。这是一种不好的做法,提供的每一种解决方案都会使情况变得更糟。
  • 我同意。甚至没有理由尝试回答这个问题,因为执行此类活动是 SQL 的基本功能。然后你可以SELECT * FROM table where id in ("pattern")

标签: mysql sql csv


【解决方案1】:

您可以使用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') ;

【讨论】:

    【解决方案2】:

    正如 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 来帮助您将数据提取为新的规范化格式

    【讨论】:

      【解决方案3】:

      我继承了这种存储小整数列表的方法,并编写了包含的函数来将整数的 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

      在您将值列表存储为 CSV 的情况下:

      从 TableX 中选择 ID、ValueList

      ID : 值列表

      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

      使用该函数将值转换为一列:

      select ID, vl.* from TableX cross apply 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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-09
        • 1970-01-01
        • 1970-01-01
        • 2018-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多