使用SQL查找精确值

3

我有这样一张表:

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
...

不使用“group by”连接,是否有可能完成此操作?

[编辑] 对于“group by concatenation”,我指的是像MySql中的GROUP_CONCAT()或任何字符串函数。


1
你正在使用哪个数据库? - KrazzyNefarious
顺序重要吗?换句话说,您是否要查找匹配的“序列”?这是我的意思:在您的示例中,(7,2,3) 的结果为9。那么 (2,7,3) 应该得到什么结果? - Jeremy Danyow
“group by concatenation” 您指的是什么意思? - user330315
您应该解释为什么“group by”不适用,因为看起来大多数解决方案都会使用它。这不是http://codegolf.stackexchange.com/。您还应该说明您到目前为止尝试了什么,并且考虑到您显然正在使用可变长度参数列表进行搜索,指示您打算如何调用该搜索将非常有帮助。 - perfectionist
无法为这个问题想出一个准确的标题,否则我会发布编辑,但“在SQL中搜索精确值”非常误导。有什么想法吗? - perfectionist
4个回答

0

group by/concatenation方法可行。另一种方法是使用带有having子句的group by

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要求提供一种不使用group by的解决方案。 - Fabian Bigler
"and count(distinct (case when b in (2, 7) then b end))" 看起来是一个正确的条件。 - user330315
@FabianBigler...用户要求不使用“分组连接”的解决方案。 - Gordon Linoff

0

在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 没有任何意义。 - user330315

0

不确定您所说的“串联分组”是什么意思 - 我认为这是不可能在没有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);

0

另一种方法是使用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

演示代码


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接