sql 与动态输入集相交

sql intersect with dynamic input set

我正在尝试弄清楚如何获取动态输入集的交集。这是一个非常简单的例子。

company_status table:

COMPANY | STATUS
----------------
  Big   |   1
Notused |   0
 Small  |   1

company_country table:

COMPANY | COUNTRY
-----------------
  Big   |   CA
  Big   |   US
Notused |   CA
Notused |   FR
 Small  |   US
 Small  |   IT

我想要的只是某些公司的国家交集。

如果我 select 只有 status = 1 的公司,这是我的预期输出:

US

如果我 select 只有 status = 0 的公司,这是我的预期输出:

CA
FR

将 company_status table 排除在外,这就是我需要的:

select country from company_status where company = 'Big'
intersect
-- ... (here is where the dynamic part comes in)
intersect
select country from company_status where company = 'Small';

但是如何将 company_status 添加到其中?

基本查询是:

select cc.country
from company_country cc join
     company_status cs
     on cc.company = cs.company
group by cc.country

然后使用 having 子句进行过滤。我认为这两个过滤器是:

having min(status) = max(status) and min(status) = 1
having sum(case when status = 0 then 1 else 0 end) > 0

这些对应于您示例中指定的结果集。

如果我理解正确,那么您只需要这些国家/地区,它们在 company_status 的每一行中都满足条件 status = 1 或 status = 0。

如果是这样你可以数一数在company_status中有多少次出现并在having-子句中使用它。但是您当然必须将相同的条件放入连接的 where 子句中。

WITH 
company_status as (
  select 'BIG' COMPANY, 1 STATUS from dual union all
  select 'NOTUSED' COMPANY, 0 STATUS from dual union all
  select 'SMALL' COMPANY, 1 STATUS from dual
),
company_country as (
  select 'BIG' COMPANY, 'CA' COUNTRY from dual union all
  select 'BIG' COMPANY, 'US' COUNTRY from dual union all
  select 'NOTUSED' COMPANY, 'CA' COUNTRY from dual union all
  select 'NOTUSED' COMPANY, 'FR' COUNTRY from dual union all
  select 'SMALL' COMPANY, 'US' COUNTRY from dual union all
  select 'SMALL' COMPANY, 'IT' COUNTRY from dual
)
select cc.country
from company_country cc join
     company_status cs
     on cc.company = cs.company
where cs.status = 0
group by cc.country
having count(*) = (SELECT COUNT(*) FROM company_status where status = 0);

(with- 子句仅提供您的行,其余问题应该适用于您的示例)

但是您可以使用 with- 子句来确定您只在一个地方想要哪个状态(第三个 with- 子句,将是您的第一个):

WITH 
company_status as (
  select 'BIG' COMPANY, 1 STATUS from dual union all
  select 'NOTUSED' COMPANY, 0 STATUS from dual union all
  select 'SMALL' COMPANY, 1 STATUS from dual
),
company_country as (
  select 'BIG' COMPANY, 'CA' COUNTRY from dual union all
  select 'BIG' COMPANY, 'US' COUNTRY from dual union all
  select 'NOTUSED' COMPANY, 'CA' COUNTRY from dual union all
  select 'NOTUSED' COMPANY, 'FR' COUNTRY from dual union all
  select 'SMALL' COMPANY, 'US' COUNTRY from dual union all
  select 'SMALL' COMPANY, 'IT' COUNTRY from dual
),
wished_status as (select 0 wished_status from dual)
select cc.country
from company_country cc 
join company_status cs on cc.company = cs.company
JOIN wished_status s on cs.status = s.wished_status
group by cc.country
having count(*) = (SELECT COUNT(*) FROM company_status cs join wished_status s on cs.status = s.wished_status);

因此您只需在 wished_status

中在 0 和 1(或任何您需要的)之间进行更改