从表中选择第二个表中没有相关条目的行

时间:2015-04-11 16:15:34

标签: sql postgresql join left-join

这是我在使用PostgreSQL 9.4的SQL的第一天,我迷失了一些东西。我认为我很接近但不够:

表格定义:

CREATE TABLE DOCTOR (
    Doc_Number INTEGER,
    Name    VARCHAR(50) NOT NULL,
    Specialty   VARCHAR(50) NOT NULL,
    Address VARCHAR(50) NOT NULL,
    City    VARCHAR(30) NOT NULL,
    Phone   VARCHAR(10) NOT NULL,
    Salary  DECIMAL(8,2) NOT NULL,
    DNI     VARCHAR(10) UNIQUE
    CONSTRAINT pk_Doctor PRIMARY KEY (Doc_Number)
  );

CREATE TABLE VISIT (
    Doc_Number    INTEGER,
    Pat_Number    INTEGER,
    Visit_Date    DATE,
    Price           DECIMAL(7,2),
    CONSTRAINT Visit_pk PRIMARY KEY (Doc_Number, Pat_Number, Visit_Date),
    CONSTRAINT Visit_Doctor_fk FOREIGN KEY (Doc_Number) REFERENCES DOCTOR(Doc_Number),
    CONSTRAINT Visit_PATIENT_fk FOREIGN KEY (Pat_Number) REFERENCES PATIENT(Pat_Number)
  );

我需要如何将这两个查询合并为一个:

SELECT d.City, d.Name
FROM DOCTOR d, VISIT v
WHERE d.Specialty = 'family and comunity' 
ORDER BY d.Name;

SELECT * FROM VISIT
WHERE DATE (Visit_Date)<'01/01/2012' 
            OR DATE(Visit_Date)>'31/12/2013';

我尝试过类似的东西,但它不起作用。我需要在2012年和2013年没有访问过该专业的医生。

SELECT City, Name
FROM DOCTOR d
WHERE d.Specialty = 'family and comunity' 
      AND NOT IN(SELECT *
        FROM VISIT 
        WHERE Visit_Date BETWEEN '2012-01-01' and '2013-12-31')
ORDER BY d.Name;

有人可以帮忙吗?

4 个答案:

答案 0 :(得分:2)

SELECT d.name, d.city
FROM   doctor     d
LEFT   JOIN visit v ON v.doc_number = d.doc_number
                   AND v.visit_date BETWEEN '2012-01-01' AND '2013-12-31'
WHERE  d.specialty = 'family and community'  -- or 'family and comunity'?
AND    v.doc_number IS NULL
ORDER  BY d.name;
  • 如您所说,您需要加入条件。访问如何与医生联系?通常情况下,您会visit.doctor_id引用doctor.doctor_id

  • 使用LEFT JOIN / IS NULL排除在上述期间访问过的医生。这是几种可能的技术之一:

  • 日期必须大于小于上限的下限 AND OR 在这里会出错。

  • 最好使用ISO 8601日期格式,无论您的语言环境如何,都明确无误。

答案 1 :(得分:2)

LEFT JOIN ... WHERE NULL构造的替代方法是普通WHERE NOT EXISTS(...)反连接。 [它完全等同于erwin的查询]

SELECT d.name, d.city
FROM   doctor  d
WHERE  d.specialty = 'family and community'
AND NOT EXISTS (
    SELECT 13
    FROM visit v WHERE v.doc_number = d.doc_number
                   AND v.visit_date BETWEEN '2012-01-01' AND '2013-12-31'
    )
ORDER  BY d.name;

答案 2 :(得分:0)

你几乎就在那里......而不是

SELECT City, Name
FROM DOCTOR d
WHERE d.Specialty = 'family and comunity' 
      AND NOT IN(SELECT *
        FROM VISIT 
        WHERE Visit_Date BETWEEN '2012-01-01' and '2013-12-31')
ORDER BY d.Name;

SELECT City, Name
FROM DOCTOR d
WHERE d.Specialty = 'family and comunity' 
      AND doc_number NOT IN(SELECT doc_number -- or SELECT DISTINCT doc number - to get fewer rows from the subquery
        FROM VISIT 
        WHERE Visit_Date BETWEEN '2012-01-01' and '2013-12-31')
ORDER BY d.Name;

以防万一 - 默认情况下,表格/列名称在Postgres中不区分大小写。如果你希望它们区分大小写 - 你必须在&#34;&#34;

答案 3 :(得分:0)

我终于找到了解决方案,这与你的解决方案非常相似,我在这里发帖帮助其他有类似问题的人

SELECT City, Name
FROM DOCTOR d, VISIT v
WHERE d.Specialty = 'family and comunity' 
          AND not exists(SELECT *
          FROM visit v WHERE v.doc_number = d.doc_number
          AND v.visit_date BETWEEN '2012-01-01' AND '2013-12-31')      
GROUP BY name, city
ORDER BY d.Name;

谢谢大家的帮助!