使用否定子句加入

时间:2014-09-03 21:01:21

标签: sql postgresql

我在Postgres数据库中找到了下表:

示例

---------------------------
   name     |    number
---------------------------
DefaultName |       1
DefaultName |       2
DefaultName |       3
DefaultName |       4
Charlie     |       1
Charlie     |       3
Charlie     |       4
Charlie     |       5
Amanda      |       2
Amanda      |       3
Amanda      |       4
Amanda      |       5

我需要获取'默认名称'中存在的"数字"但是每个"名称" s中不存在' defaultName中&#39 ;. 在这种情况下,它会返回:

---------------------------
   names    |    numbers
---------------------------
Charlie     |       2
Amanda      |       1

我正在尝试像下面这样的左连接,但是我无法找到一种方法来将DefaultName数字与其他名称相交并且#39; ...

SELECT Test_Configs.name, Default_Configs.number

FROM Example AS Test_Configs  
    LEFT JOIN Example AS Default_Configs      
        ON Default_Configs.name = 'DefaultName'

3 个答案:

答案 0 :(得分:3)

我会为每个名称生成整个范围,并为基表生成LEFT JOIN以消除当前名称:

SELECT n.name, nr.number
FROM  (
   SELECT DISTINCT name
   FROM   example
   WHERE  name <> 'DefaultName'
   ) n                         -- all names except 'DefaultName'
CROSS  JOIN (
   SELECT number               -- assuming distinct numbers for 'DefaultName'
   FROM   example
   WHERE  name = 'DefaultName'
   ) nr                        -- combine with numbers from 'DefaultName'
LEFT   JOIN example x USING (name, number)
WHERE  x.number IS NULL;       -- minus existing ones

仅列出每个名称的间隙:

SELECT n.name, nr.number
FROM  (
   SELECT name, min(number) AS min_nr, max(number) AS max_nr
   FROM   example
   GROUP  BY 1
   ) n
 , generate_series(n.min_nr, n.max_nr) AS nr(number)
LEFT   JOIN example x USING (name, number)
WHERE  x.number IS NULL;

SQL Fiddle.

以下是排除另一个表中存在的行的基本技术(本例中的派生表):

答案 1 :(得分:2)

需要几次传递,选择默认值,组名不是默认值,然后是左连接并检查空值。查看SQLFiddle示例。

select Names.name, DefaultConfigs.number
from Example DefaultConfigs
  cross join (
    select name
    from Example
    where name != 'DefaultName'
    group by name
    ) Names
  left join Example Missing on Missing.name = Names.name
    and Missing.number = DefaultConfigs.number
where DefaultConfigs.name = 'DefaultName'
  and Missing.name is null
;

答案 2 :(得分:1)

构建名称和默认号码的所有组合。然后删除那些在场的人。

select othernames.name, defaultnumbers.number
from (select number from example where name = 'DefaultName') defaultnumbers
cross join (select distinct name from example where name <> 'DefaultName') othernames
except
select name, number from example;