2

这个查询有什么问题:

WITH volcan AS (SELECT DISTINCT v.numturista
                FROM viaje v, sitio s
                WHERE v.numsitio = s.numsitio
                AND s.tipo = 'Volcan'),
    desierto AS (SELECT DISTINCT v.numturista
                 FROM viaje v, sitio s
                 WHERE v.numsitio = s.numsitio
                 AND s.tipo = 'Desierto')
SELECT DISTINCT pais
FROM turista
WHERE numturista IN (volcan INTERSECT desierto);

它不应该等同于以下内容吗(因为 WITH 创建了命名的 SELECT 查询):

SELECT DISTINCT pais
FROM turista
WHERE numturista IN (
(SELECT DISTINCT v.numturista
                FROM viaje v, sitio s
                WHERE v.numsitio = s.numsitio
                AND s.tipo = 'Volcan')
INTERSECT
(SELECT DISTINCT v.numturista
                 FROM viaje v, sitio s
                 WHERE v.numsitio = s.numsitio
                 AND s.tipo = 'Desierto')
);

它说:

syntax error near INTERSECT.

Postgres 版本:psql (PostgreSQL) 9.1.9

更新:测试表

CREATE TABLE turista (
    numturista INTEGER,
    nomturista VARCHAR(100),
    pais VARCHAR(100),
    PRIMARY KEY(numturista)
);

CREATE TABLE sitio (
    numsitio INTEGER,
    nomsitio VARCHAR(100),
    tipo VARCHAR(100),
    continente VARCHAR(100),
    PRIMARY KEY(numsitio)
);

CREATE TABLE viaje (
    numviaje VARCHAR(7),
    numturista INTEGER,
    numsitio INTEGER, 
    fechasalida DATE,
    fechallegada DATE,
    ciudadsalida VARCHAR(100),
    PRIMARY KEY(numviaje, numturista, numsitio),
    FOREIGN KEY(numsitio) REFERENCES sitio,
    FOREIGN KEY(numturista) REFERENCES turista
);

INSERT INTO turista VALUES
 (300, 'Carlos', 'Costa Rica')
,(301, 'Pierre', 'Francia')
,(302, 'John', 'Jamaica')
,(303, 'Mario', 'Panama')
,(304, 'Ali', 'Tunez')
,(305, 'Ana', 'Guatemala');

INSERT INTO sitio VALUES 
 (125, 'Isla Moorea', 'Mar Litoral', 'Oceania')
,(126, 'Bahia Matsushima', 'Mar Litoral', 'Asia')
,(127, 'Irazu', 'Volcan', 'America')
,(128, 'Ngorongoro', 'Volcan', 'Africa')
,(129, 'Valle de la Muerte', 'Desierto', 'America')
,(130, 'Kilimandjar', 'Volcan', 'Africa');

INSERT INTO viaje VALUES
 ('03-2012', 301, 125, '2013-03-03', '2013-10-03', 'Paris')
,('04-2012', 303, 129, '2013-04-07', '2014-02-07', 'Las Vegas')
,('05-2012', 301, 128, '2013-05-07', '2013-12-07', 'Dar-es-Salam')
,('06-2012', 304, 127, '2013-06-07', '2014-02-07', 'San Jose')
,('07-2012', 302, 128, '2015-04-11', '2014-01-08', 'Mombasa')
,('04-2012', 305, 129, '2013-04-07', '2014-02-07', 'Las Vegas')
,('06-2012', 305, 127, '2013-06-07', '2014-02-07', 'San Jose');
4

1 回答 1

5

这将是等效的:

WITH volcan AS (
    SELECT DISTINCT v.numturista
    FROM   viaje v
    JOIN   sitio s USING (numsitio)
    WHERE  s.tipo = 'Volcan'
   )
, desierto AS (
    SELECT DISTINCT v.numturista
    FROM   viaje v
    JOIN   sitio s USING (numsitio)
    WHERE  s.tipo = 'Desierto'
   )
SELECT DISTINCT pais
FROM   turista
WHERE  numturista IN ((TABLE volcan) INTERSECT (TABLE desierto));

但它可能非常低效......

TABLE tbl只是SELECT * FROM tbl.

替代查询

尝试这个:

SELECT pais
FROM   turista t
WHERE  EXISTS (SELECT 1 FROM viaje v JOIN sitio s USING (numsitio)
               WHERE  v.numturista = t.numturista AND s.tipo = 'Volcan')
AND    EXISTS (SELECT 1 FROM viaje v JOIN sitio s USING (numsitio)
               WHERE  v.numturista = t.numturista AND s.tipo = 'Desierto')

做同样的事情,只是更简单,更快。使用EXISTS,您不需要任何DISTINCT子句,除非您确实有重复的国家/地区(pais),我对此表示严重怀疑。

于 2013-06-14T15:58:17.197 回答