让我们想象一下我有两张桌子
**T1**
T1ID
----
1
2
3
**T2**
T2ID| T1ID| VALUE|
------------------
1| 1| 1|
2| 1| 2|
3| 2| 1|
4| 2| 3|
5| 2| 2|
6| 3| 1|
7| 3| 4|
T1是T2中值的分组表 因此,我有三组价值观
1 = 1, 2
2 = 1, 2, 3
3 = 1, 4
是否可以编写查询来获取与这组值匹配的所有组?
SELECT … WHERE VALUE IN (1, 2, 3)
SHOULD GIVE AS RESULT
1
2
SELECT … WHERE VALUE IN (1, 4)
SHOULD GIVE AS RESULT
3
下面的答案之一指出我要以适当的方式挖掘:
SELECT s.t1id
FROM (SELECT t1id, COUNT(value) itemCount
FROM t2
WHERE VALUE IN (1, 2, 3) -- put set of values here
GROUP BY t1id) s
JOIN (SELECT t1id, COUNT(VALUE) itemCount
FROM t2
GROUP BY t1id) j
ON s.t1id = j.t1id
WHERE s.itemCount >= j.itemCount
有人可以改进查询吗?
答案 0 :(得分:0)
您可以通过多种方式实现这一目标。相反的测试("不在列表中#34;)可以产生有趣的解决方案:
SELECT t1id
FROM t2
GROUP BY t1id
HAVING COUNT(CASE WHEN value NOT IN (1,4) THEN 1 END) = 0
上述查询不包括表 t2 中根本没有值的那些键。严格来说,空集是任何其他集的子集,因此实际上也应列出这些键。使用外连接可以实现,如下所示:
SELECT t1.t1id
FROM t1
LEFT JOIN t2
ON t1.t1id = t2.t1id
GROUP BY t1.t1id
HAVING COUNT(CASE WHEN value NOT IN (1,4) THEN 1 END) = 0
或者,将IN
测试作为外连接条件:
SELECT t1.t1id
FROM t1
LEFT JOIN t2
ON t1.t1id = t2.t1id
AND value NOT IN (1,4)
WHERE t2.t1id IS NULL
GROUP BY t1.t1id
或者,使用子查询:
SELECT t1id
FROM t1
WHERE t1id NOT IN (SELECT t1id
FROM t2
WHERE value NOT IN (1,4))
您也可以使用MINUS
,这非常直观:
SELECT t1id
FROM t1
MINUS
SELECT t1id
FROM t2
WHERE t1id NOT IN (1,4)
快速查看您的案例中表现最佳的内容。
答案 1 :(得分:0)
我写了以下内容......不确定您是否使用Oracle,但这似乎有效。如果这对您更有效,请告诉我。
select *
from
(
select
t1_id,
LISTAGG(value, '') WITHIN GROUP (ORDER BY value) value_list
from
(
select 1 t1_id, 1 value from dual union all
select 1 t1_id, 2 value from dual union all
select 2 t1_id, 1 value from dual union all
select 2 t1_id, 3 value from dual union all
select 2 t1_id, 2 value from dual union all
select 3 t1_id, 1 value from dual union all
select 3 t1_id, 4 value from dual
)
t2
group by t1_id
)
where
instr('123',value_list) > 0
编辑:我注意到SQLServer标签......刚才。对于那个很抱歉。所以我用SQLServer语法重写了我的解决方案。
其他编辑:对,你是......我认为以下将纠正这种行为。但是,我不能评论下面方法的效率。我认为LISTAGG在Oracle中的内联功能可能更有效 - 只是因为比我聪明的人更优化了它。
with t2 as
(
select 1 t2_id, 1 t1_id, 1 value union all
select 2 t2_id, 1 t1_id, 2 value union all
select 3 t2_id, 2 t1_id, 1 value union all
select 4 t2_id, 2 t1_id, 3 value union all
select 5 t2_id, 2 t1_id, 2 value union all
select 6 t2_id, 3 t1_id, 1 value union all
select 7 t2_id, 3 t1_id, 4 value
)
SELECT
*
FROM
(
SELECT DISTINCT
b.t1_id,
STUFF(CAST((
SELECT [text()] = '' + cast(a.Value AS VARCHAR(100))
FROM t2 a
WHERE a.t1_id = b.t1_id
ORDER BY a.Value
FOR XML PATH(''), TYPE) AS VARCHAR(1000)), 1, 0, ''
) value_list
from
t2 b
) x
where
CHARINDEX(value_list,'123',1) > 0 OR
CHARINDEX('123',value_list,1) > 0
最终编辑:对不起,我已经在评论中做了这些,如果我没有被认为太新用户被允许发表评论。我认为你是对的。我没有完全理解这些要求,但我已经开始了。如果我们在t2中添加一个值(1,3),我的过程将再次在搜索' 123'时失败。我认为我目前的解决方案是错误的,但我认为可能有一些优点可以进行解包和排序,以实现更有效的模式匹配。但是,它可能会取消它的LISTAGG部分。但是,既然你已经有了一个有效的解决方案,那么我最好退出并对更有成效的问题进行痴迷。
抱歉,我没有帮助,哈哈。先生,祝你好运。