MySql - 查找在不使用聚合函数的情况下发生两次的值

时间:2014-08-21 21:06:25

标签: mysql sql database

表:的城市

City_Name (PK)    State_Name (PK)    Population
--------------    ---------------    ----------
Austin            MA
Austin            TX
Burlington        VT
Fresno            CA
Houston           TX
Independence      KS
Independence      MO
Independence      PA 
Kansas            CA 
Kansas            MO
Paris             MO 
Paris             OR 
Paris             TX 
Paris             VA  
Paso              TX

上表有一个复合主键(City_Name和State_Name)。我想找到恰好发生在两个不同国家的城市(不多也不少)。在这种情况下,结果将是

City_Name
---------
Austin
Kansas

其他城市不符合条件,因为它们出现在一个或两个以上的州。这个解决方案是练习关系演算问题所必需的,因此(不幸的是)不能使用任何聚合函数,如COUNT()。

期待收到一些善良的人的回复。

注意 - 没有找到任何线索从哪里开始,因此不会显示任何努力:(

4 个答案:

答案 0 :(得分:4)

select distinct c1.city_name
from city c1
  join city c2 
    on c2.city_name = c1.city_name 
   and c1.state_name <> c2.state_name
where not exists (select 1
                from city c3
                where c3.city_name = c1.city_name 
                  and c3.state_name not in (c1.state_name, c2.state_name));   

SQLFiddle:http://sqlfiddle.com/#!2/7d0901/8

答案 1 :(得分:2)

似乎mysql不支持minus / except:

-- two or more states 
select c1.city_name 
from city c1 
join city c2 
    on c1.city_name = c2.city_name 
   and c1.state_name<>c2.state_name 
minus
-- three or more states
select c1.city_name 
from city c1 join city c2 
    on c1.city_name = c2.city_name 
   and c1.state_name<>c2.state_name 
join city c3 
    on c1.city_name = c3.city_name 
   and c1.state_name <> c3.state_name 
   and c2.state_name <> c3.state_name;

使用not in:

进行重写
-- two or more states
select distinct c1.city_name 
from city c1 
join city c2 
    on c1.city_name = c2.city_name 
   and c1.state_name<>c2.state_name 
where c1.city_name not in (
    -- three or more states
    select c1.city_name 
    from city c1 
    join city c2 
        on c1.city_name = c2.city_name 
       and c1.state_name<>c2.state_name 
    join city c3 
        on c1.city_name = c3.city_name 
        and c1.state_name <> c3.state_name 
        and c2.state_name <> c3.state_name
);

答案 2 :(得分:2)

@ a_horse_with_no_name的答案是一个非常好(并且直截了当)的解决方案。以下是完成同样事情的另一种方式:

SELECT DISTINCT c1.city_name
FROM   city c1
       JOIN city c2
          ON c2.city_name = c1.city_name AND c1.state_name <> c2.state_name
       LEFT JOIN city c3
          ON     c1.city_name = c3.city_name
             AND c3.state_name NOT IN (c1.state_name, c2.state_name)
WHERE  c3.city_name IS NULL

此解决方案在FROM子句中创建一组2-3个城市,然后使用where子句清除那些拥有第三个城市的城市。

答案 3 :(得分:1)

因此,此查询将计算重复行的数量,并将删除计数高于2的那些以及计数较低的那些2.尝试出来! :)

SELECT DISTINCT city_name 
FROM city
WHERE city_name NOT IN
(   SELECT IF(counting_col > 2, city_name, NULL) AS city_name_s 
    FROM
    (   SELECT city_name, IF(@A = city_name, @B := @B + 1, @B := 1) AS counting_col, @A := city_name
    FROM city
    CROSS JOIN (SELECT @A := '', @B := 1) t
    ORDER BY city_name
    ) t1
    HAVING city_name_s IS NOT NULL
)
AND city_name IN
(   SELECT IF(counting_col = 2, city_name, NULL) AS city_name_s 
    FROM
    (   SELECT city_name, IF(@A = city_name, @B := @B + 1, @B := 1) AS counting_col, @A := city_name
    FROM city
    CROSS JOIN (SELECT @A := '', @B := 1) t
    ORDER BY city_name
    ) t1    
    HAVING city_name_s IS NOT NULL
)

DEMO