获取数据子集的零计数

时间:2017-02-01 16:36:48

标签: sql oracle

我无法弄清楚我认为必须是一个非常简单的问题。我真的很生气我把这个问题搞得很困难,但我已经准备好问别人了。

我有一个基本上是一堆键值对的表,其中键和值都可以重复。我有另一个表可以用来过滤第一个表中的值。

我想从第二个表中获取值,并使用它来过滤第一个表中的键值对,并获得GROUP BY计算第一个表中剩余的键数。我还希望当第二个表导致给定键的所有行被过滤掉时,该计数返回0。

我知道可能很难想象,所以这里有一个SQL Fiddle链接: http://sqlfiddle.com/#!4/c186ef

不幸的是,我似乎无法让SQL Fiddle运行我放在那里的查询,即使我可以在我的IDE中运行它。但希望这能传达出我想要做的事情。 以下是我一直在尝试对付SQL Fiddle中的表的SQL语句:

SELECT mtkv2.key, COALESCE(count(mtkv2.value), 0) cnt
  FROM matt_test_key_values mtkv1
 RIGHT OUTER JOIN matt_test_key_values mtkv2 ON mtkv1.key = mtkv2.key 
 WHERE mtkv2.value in (SELECT value FROM matt_test_values)  
 GROUP BY mtkv2.key

SELECT mtkv1.key, COALESCE(count(mtkv1.key), 0) cnt
  FROM matt_test_key_values mtkv1
 WHERE mtkv1.value not in (SELECT value FROM matt_test_values)
 GROUP BY mtkv1.key

SELECT mtkv1.key, COALESCE(count(mtkv1.value), 0) cnt
  FROM matt_test_key_values mtkv1
  LEFT JOIN matt_test_key_values mtkv2 ON mtkv1.key = mtkv2.key
   AND mtkv1.value = mtkv2.value
   AND mtkv2.value IN (SELECT value FROM matt_test_values)
 GROUP BY mtkv1.key

我一直在搞乱不同的SQL,所以此时可能还有其他一些错误。我并没有问过如何解决这些问题,因为我试图找出应该如何正确地完成这些工作

示例数据可以在SQL Fiddle中看到,但这里只是以下情况:

create table matt_test_values (value varchar2(200))
insert into matt_test_values values('1')
create table matt_test_key_values (key varchar2(200), value varchar2(200))
insert into matt_test_key_values values('1', '1')
insert into matt_test_key_values values('1', '2')
insert into matt_test_key_values values('1', '3')
insert into matt_test_key_values values('2', '1')
insert into matt_test_key_values values('2', '2')
insert into matt_test_key_values values('3', '1')
insert into matt_test_key_values values('4', '2')

我希望获得的输出类似于:

key   cnt
---   ---
1     2 //after removing the "1" value that matches, there are two rows left
2     1 //after removing the "1" value that matches, there is one row left
3     0 //after removing the "1" value that matches, there are zero rows left - this is the result I am having trouble getting
4     1 //after removing the "1" value that matches, there is one row left

3 个答案:

答案 0 :(得分:1)

技巧是捕获所有值都被消除的键的零计数。此解决方案使用子查询来获取所有键的集合;外连接意味着当剩余键组中没有匹配时,你将得到0。

with cte as (
    select distinct key
    from matt_test_key_values
    )
    , mtkv as (
    select * from matt_test_key_values 
    where value not in ( select mtv.value from matt_test_values mtv)
    )
select cte.key
        , count(mtkv.value) vals
from cte
     left outer join mtkv
     on mtkv.key = cte.key
group by cte.key
order by cte.key
/ 
  

"键和值都可以重复"

我的解决方案计算所有键/值对而不是不同的键/值对。如果这不是您想要的,那么改变逻辑就很容易了。

答案 1 :(得分:1)

How about

select distinct m.key, nvl( g.c, 0 )
from matt_test_key_values m
left join (
   select k.key, count(*) c
   from matt_test_key_values k
   left join matt_test_values v
     on k.value = v.value
   where v.value is null
   group by k.key
   ) g
on m.key = g.key

答案 2 :(得分:0)

示例输出会很有帮助,但是根据您的描述,它听起来像这样:

select key, count(*)
from matt_test_key_values
where value not in ( select value from matt_test_values )
group by key