如何获取SET列中包含未知值的行



数据库为MySQL 5.6

CREATE TABLE set_t
(
set_r  SET ('a', 'b', 'c')
);
INSERT INTO set_t (set_r) VALUES ('a,b,c'), ('a,b');

就我而言,我只知道"a"one_answers"b"。

例如,需要选择set_r为"的行;a、 b、c";。

值"c"未知,无法在查询中使用。

值的顺序也是未知的。它们可以是set_r set('c','b','a'(或else。

如何选择包含未知值的行?

对样本数据执行此操作的简单方法是使用NOT IN:

SELECT *
FROM set_t
WHERE set_r NOT IN ('a', 'b', 'a,b')

但是,如果您有更大的集合,并且您希望在已知成员列表中包含比ab更多的成员,则这不会很好地扩展

集合的每个成员都存储为一个数值
在您的设置中,数值为:

SET Member  Decimal Value   Binary Value
'a'         1               001
'b'         2               010
'c'         4               100

因此,像'a,b'这样的值被存储为3(二进制011(
,而像'a,b,c'这样的值则被存储为7(二进制111(

如果你知道已知成员的数值,你可以通过它们在集合中定义的顺序来获得,那么你可以使用位运算来获得你想要的:

SELECT *
FROM set_t
WHERE set_r | 3 <> 3 -- 3 is the numeric value of 'a,b'

或:

SELECT *
FROM set_t
WHERE set_r | 0b11 <> 0b11 -- 0b11 is the numeric binary value of 'a,b'

请参阅演示

您可以使用find_in_set()来检查各个值。请参阅此处的SET文档

select * from set_t where find_in_set('a', set_r) and find_in_set('b', set_r)

这会给你

set_r
(a,b,c(
(a,b(

最有效的方法是使用二进制比较。这假设您知道'a''b'在集合中的位置:

select *
from set_t
where (set_r | b'11') <> b'11';

您也可以使用字符串操作来完成此操作。这有点痛苦,因为您需要处理逗号分隔符:

select *
from set_t
where replace(replace(replace(concat(',', set_r, ','), ',a,', ','), ',b,', ','), ',', '') <> ''

逻辑是:

  • set_r的开头和结尾放置分隔符
  • 删除带分隔符的元素,将其替换为分隔符
  • 检查结果是否只有分隔符

无论集的大小和要比较的元素的位置如何,此版本都能正常工作。

这里有一个db<gt;不停摆弄

最新更新