使用 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 byhaving 子句:

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 搜索精确值的主要内容,如果未能解决你的问题,请参考以下文章

查询反模式 - 全文搜索

使用弹性搜索查询查找多个精确值

sql 模糊搜索无输入参数时查询所有

具有精确词匹配搜索的 RDD 过滤器

弹性搜索查询在regexp输入参数的列表中查找值的精确匹配

ElasticSearch结构化搜索和全文搜索