使用 SQL 搜索精确值
Posted
技术标签:
【中文标题】使用 SQL 搜索精确值【英文标题】:Searching exact values with SQL 【发布时间】:2014-03-27 10:59:10 【问题描述】:我有这种桌子:
a b
8 7
8 2
9 7
9 2
9 3
我想获得一个“a”值,使其具有“b”的精确搜索值。例如,如果我搜索 (7,2),我希望查询返回 8,如果我搜索 (7,2,3),我希望它返回 9,否则它必须返回 Null:
Search Result
(7,2) 8
(7,2,3) 9
(7,3) Null
(7,2,4) Null
...
是否可以不使用“分组依据”连接来做到这一点?
[编辑] 对于“按连接分组”,我的意思是 mysql 中的 GROUP_CONCAT() 或任何字符串函数。
【问题讨论】:
你正在使用的数据库? 顺序重要吗?换句话说,您是否正在寻找匹配的“序列”?这就是我的意思:在您的示例中,您的 (7,2,3) 结果为 9。 (2,7,3) 结果应该是什么? “按连接分组”到底是什么意思 您应该解释为什么“分组依据”不合适,因为看起来大多数解决方案都会包含它。这不是codegolf.stackexchange.com 您还应该解释到目前为止您已经尝试过的内容,并且鉴于您显然是在使用可变长度参数列表进行搜索,这将有助于您说明您打算如何调用该搜索。 想不出这个问题的准确标题,或者我会发布编辑,但“在 sql 中搜索确切值”非常具有误导性。有什么想法吗? 【参考方案1】:group by
/连接方法有效。另一种方法是group by
与having
子句:
select a
from table t
group by a
having sum(case when b = 7 then 1 else 0 end) = 1 and
sum(case when b = 2 then 1 else 0 end) = 1 and
sum(case when b not in (7, 2) then 1 else 0 end) = 0;
这个想法是计算每个值中匹配的值。您实际上可以使用字符串操作来做到这一点,但这些操作在数据库之间有所不同。这是使用in
和您要查找的值的数量的“一般”方式:
select a
from table t
group by a
having count(*) = 2 and
count(distinct (case when b in (2, 7) then b end));
【讨论】:
其实 OP 要求一个解决方案 without group by。and count(distinct (case when b in (2, 7) then b end))
似乎是一个合适的条件
@F***Bigler 。 . .用户要求没有“按串联分组”的解决方案。【参考方案2】:
不确定“按连接分组”是什么意思 - 我认为 没有 group by
:
您没有指定您的 DBMS,所以这是 ANSI SQL:
with search_values (val) as (
values (7), (2)
)
-- first part gets all those that do have the search values
-- but will also include those rows that have more than the searched ones
select a
from data
where b in (select val from search_values)
group by a
having count(distinct b) = (select count(*) from search_values)
intersect
-- the intersect then filters out those that have exactly the search values
select a
from data
group by a
having count(distinct b) = (select count(*) from search_values);
SQLFiddle 示例:http://sqlfiddle.com/#!15/dae93/1
对“搜索值”使用 CTE 可避免重复它们,并避免“硬编码”要搜索的项目数。如果您查找 7、2、3,您只需向 CTE 添加另一个值
除了使用intersect
,它可以用一个相关的子查询重写
with search_values (val) as (
values (7), (2)
)
select d1.a
from data d1
where d1.b in (select val from search_values)
group by d1.a
having count(distinct d1.b) = (select count(*) from search_values)
and count(distinct d1.b) = (select count(*) from data d2 where d2.a = d1.a);
【讨论】:
【参考方案3】:在 SQL Server 中
SELECT a FROM tableName
WHERE a NOT IN ( SELECT a FROM (
SELECT a,
CASE WHEN CHARINDEX(b,@searchTerm)=0
THEN 0 ELSE 1 END as Result
FROM tableName
)z
WHERE z.Result=0
)
我正在使用 CHARINDEX() 函数来检查搜索词是否存在。
【讨论】:
使用charindex
对于其中只有一个值的数字列没有任何意义。【参考方案4】:
另一种方法是使用 INTERSECT。
但是,第一种情况似乎是一个仍然需要破解的坚果(返回 8,9 而不是 8)。
这是 SQL 代码:
--(7,2) => 8,9 (instead of 8) :(
SELECT distinct(a)
FROM t1
WHERE b = 7
INTERSECT
SELECT distinct(a)
FROM t1
WHERE b = 2
--(7,2,3) => 9
SELECT distinct(a)
FROM t1
WHERE b = 7
INTERSECT
SELECT distinct(a)
FROM t1
WHERE b = 2
INTERSECT
SELECT distinct(a)
FROM t1
WHERE b = 3
--(7,4) => NULL
SELECT distinct(a)
FROM t1
WHERE b = 7
INTERSECT
SELECT distinct(a)
FROM t1
WHERE b = 4
--(7,2,4) => NULL
SELECT distinct(a)
FROM t1
WHERE b = 7
INTERSECT
SELECT distinct(a)
FROM t1
WHERE b = 2
INTERSECT
SELECT distinct(a)
FROM t1
WHERE b = 4
Fiddle Demo
【讨论】:
以上是关于使用 SQL 搜索精确值的主要内容,如果未能解决你的问题,请参考以下文章