SQL查询所有A必须具有来自B的以下列相等?

时间:2012-10-17 00:56:30

标签: mysql sql logic subquery relational-division

这是我的意思的具体例子。我定义了下表:

CREATE TABLE pets (
    id INTEGER UNSIGNED NOT NULL,
    name VARCHAR(20) NOT NULL,
    breed VARCHAR(20) NOT NULL,
    color VARCHAR(20) NOT NULL,
    weight INTEGER UNSIGNED NOT NULL,
    PRIMARY KEY (id)
);

如何编写SQL查询以查找包含与可卡犬的颜色相同颜色的宠物的品种?因此,如果数据库中的所有可卡犬都是黑色或白色,我需要找到所有不同品种,至少有1只黑色宠物和1只黄色宠物。我已经被这个问题困扰了一段时间,并且无法在网上找到类似的答案,所以任何帮助都会受到赞赏。

4 个答案:

答案 0 :(得分:2)

与往常一样,保持实际RDBMS的秘密使其变得更加困难。

对于支持CTE的数据库(PostgreSQL,Oracle,SQL Server,..)

的CTE:

WITH colors AS (
    SELECT DISTINCT color
    FROM   pets
    WHERE  breed = 'cocker spaniels'
    )
SELECT p.breed
FROM   colors c
JOIN   pets   p USING (color)
GROUP  BY p.breed
HAVING count(DISTINCT p.color) = (SELECT count(*) FROM color);

解释

  1. 在CTE color中获取一组不同颜色的可卡犬。
  2. 加入所有相同颜色的宠物,按品种分组宠物
  3. HAVING条款中,确认不同颜色的数量与可卡犬的颜色数量相符。
  4. Ergo:由此产生的宠物(包括可卡犬)有可卡犬所有颜色 - 可能更多。

    这是关系划分的特例。我们最近在this related question下汇集了一大堆查询。


    对于MySQL

    SELECT p.breed
    FROM (
       SELECT DISTINCT color
       FROM   pets
       WHERE  breed = 'cocker spaniels'
       ) c
    JOIN   pets p USING (color)
    GROUP  BY p.breed
    HAVING count(DISTINCT p.color) = (
       SELECT count(DISTINCT color)
       FROM   pets
       WHERE  breed = 'cocker spaniels'
       );
    

    -> sqlfiddle

答案 1 :(得分:0)

SELECT  DISTINCT breeds  FROM pets 
WHERE color in (SELECT color FROM pets where name='cocker spaniels')

答案 2 :(得分:0)

如果我理解正确的话,你不需要品种全白或全黑的品种。你只需要白色和黑色的品种(可卡犬的不同颜色)。基于此,这就是我想出的(虽然它可能不是最有效的)。

DECLARE @pets TABLE(
  id INTEGER NOT NULL,
  name VARCHAR(20) NOT NULL,
  breed VARCHAR(20) NOT NULL,
  color VARCHAR(20) NOT NULL,
  weight INTEGER NOT NULL,
  PRIMARY KEY (id)
);

INSERT INTO @pets VALUES (1, 'jeff', 'breed1', 'black', 20)
INSERT INTO @pets VALUES (2, 'larry', 'breed1', 'white', 20)
INSERT INTO @pets VALUES (3, 'bob', 'breed2', 'black', 30)
INSERT INTO @pets VALUES (4, 'kevin', 'breed3', 'black', 30)
INSERT INTO @pets VALUES (5, 'jerry', 'breed3', 'white', 30)

DECLARE @breed VARCHAR(50)
SET @breed = 'breed1'
;WITH cte (color) AS (SELECT DISTINCT color FROM @pets WHERE breed = @breed)
SELECT breed, COUNT(id) FROM @pets WHERE color IN (SELECT color FROM cte)
  AND breed != @breed
GROUP BY breed
HAVING COUNT(id) >= (SELECT COUNT(*) FROM cte)

Result: breed3

如果您使用的是不支持CTE的SQL版本,则可以使用临时表或表变量来保存您需要在其他品种中查找的颜色。希望这有帮助!

答案 3 :(得分:0)

--parameter
DECLARE @breed varchar(20)
SET @breed = 'Cocker Spaniel' 

--count distinct colors for param
DECLARE @colors int
SELECT @colors = COUNT(DISTINCT color) FROM pets WHERE breed = @breed 

--match param breed with others based on color
--return only breed with matching count of distinct colors
SELECT otherBreeds.breed
FROM
    (SELECT DISTINCT breed, color FROM pets WHERE breed = @breed) AS thisBreed
    LEFT OUTER JOIN (SELECT DISTINCT breed, color FROM pets WHERE breed <> @breed) AS otherBreeds
    ON thisBreed.color = otherBreeds.color
GROUP BY otherBreeds.breed
HAVING COUNT(DISTINCT otherBreeds.color) = @colors