4

例如我有表 A 和表 B

a.data = {1,2,3,4,5,6} b.data = {4,5,7}

如果要在 a.data 或 b.data 中查找一个值,可以使用 FIND_IN_SET(3, b.data)。但是我想知道是否至少b.data 的所有值都在 a.data 中,或者我是否至少可以找到 b.data 和 a.data 之间的交集。所以在这种情况下{4,5}。

WHERE INTERSECT(a.data, b.data) ...类似的东西。我应该如何在 MySQL 中做到这一点?

更新

b.data {4,5,7} 是一个 1 记录的列数据,所以在 b.data 上加入 a.data 是行不通的。

table A  
=======
ID     DATA  
1      {1,2,3,4,5,6}  
2      {7,9,12}  

table B  
=======  
ID     DATA  
1      {4,5,7}  
2      {9,10,11,12}
4

3 回答 3

4

您可以使用INNER JOIN

看看联接的视觉解释

SELECT fn_intersect_string(a.data, b.data) AS result FROM table_name;

您也可以将用户定义的函数编写为:

CREATE FUNCTION fn_intersect_string(arg_str1 VARCHAR(255), arg_str2 VARCHAR(255))
RETURNS VARCHAR(255)
BEGIN
    SET arg_str1 = CONCAT(arg_str1, ",");
    SET @var_result = "";

    WHILE(INSTR(arg_str1, ",") > 0)
    DO
        SET @var_val = SUBSTRING_INDEX(arg_str1, ",", 1);
        SET arg_str1 = SUBSTRING(arg_str1, INSTR(arg_str1, ",") + 1);

        IF(FIND_IN_SET(@var_val, arg_str2) > 0)
        THEN
            SET @var_result = CONCAT(@var_result, @var_val, ",");
        END IF;
    END WHILE;

    RETURN TRIM(BOTH "," FROM @var_result);
END;
于 2012-07-26T13:31:01.340 回答
1

您从内部连接获得交集:

SELECT a.data FROM a, b WHERE a.data = b.data

要确定 b 是否是 a 的子集,您可以执行

SELECT b.data FROM b LEFT JOIN a ON a.data = b.data WHERE a.data IS NULL

这将计算差异:来自 b且不包含在 a 中的所有值。如果为空,则 b 是 a 的子集。

您可以将这两种方法用作较大查询中的子查询。

于 2012-07-26T13:26:38.807 回答
1

如果您的列是 type SET,那么它会在内部存储为一个数字,并会在适当的情况下自动转换为该数字。您描述的操作对应于这些数字的按位逻辑操作。例如,可以使用来自两列的值的逐位和计算交集。

a.data & b.data AS intersection,
(a.data & b.data) <> 0 AS aAndBIntersect,
(a.data & b.data) == b.data AS bIsSubsetOfA

这要求两列的类型相同,以便相同的字符串对应相同的位。要将结果转换回字符串,您可以使用ELT,但所有组合可能会变得丑陋。作为替代方案,您可以将结果保存在具有相同数据类型的临时表中,将其存储为数字,然后以字符串的形式检索。

于 2012-07-26T13:40:31.963 回答