如何获得两列的交集

时间:2012-07-26 13:19:25

标签: mysql

例如我有表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}。

INTERSECT(a.data,b.data)......就是这样的。我应该如何在MySQL中执行此操作?

更新

b.data {4,5,7}是一条记录的列数据,因此在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}

3 个答案:

答案 0 :(得分:3)

您可以使用INNER JOIN

获取表格的交集

查看Visual explaination of joins

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;

答案 1 :(得分: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的子集。

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

答案 2 :(得分:1)

如果您的列属于SET类型,则它会在内部存储为数字,并在适当的位置自动转换为该数字。您描述的操作对应于对这些数字的逐位逻辑运算。例如,可以使用两列值的bit-wise and来计算交集。

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

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