如何使用mysql中存在与否的方式实现交叉

时间:2014-03-11 03:15:32

标签: mysql sql database relational-database intersection

我的表是:

customer(cid,name,city,state)
orders(oid,cid,date)
product(pid,productname,price)
lineitem(lid,pid,oid,number,totalprice)

我想选择城市'X'的所有客户购买的产品。这意味着我需要交叉所有居住在城市'X'的客户购买的产品

示例:如果有3个客户c1,c2和c3我的答案是c1.product(intersect)c2.product(intersect)c3.product

我只想使用where existswhere not exists来实现这一点,因为我需要编写关于where not inwhere in不可用的关系演算。我可以部分查询是这样的:

select 
  * 
from 
  product p,
  lineitem l,
  customer c1 
where 
  exists(
   select 
      * 
   from 
     customer c,
     orders o 
   where 
    o.cid=c.cid and 
    c.city='X' and 
    l.oid=o.oid and 
    l.pid=p.pid and 
    c1.cid=c.cid)

以上查询为我提供了生活在X市的所有客户的pid,cid,oid,lid,totalprice,city,productname。现在我需要弄清楚如何选择所有客户共有的产品。

注意:

我无法使用任何聚合函数,因为它在关系演算中不可用。我有一个使用聚合函数的工作查询,这是

select 
   p.productname 
from 
   product p, 
   orders s, 
   lineitem l, 
   customer c 
where 
   l.pid=p.pid and
   l.oid=s.oid and 
   c.cid=s.cid and 
   c.city='X' 
group by 
   p.productname 
having 
   count(distinct c.cid)=(select count(*) from customer c1 where c1.city='X')

如果有人可以在不where existswhere not exists的{​​{1}}或count表单中转换上述查询,那就没问题了。

我确信它可以完成,因为我可以在关系代数中这样做,并且根据Codd's theorom元组关系演算和关系代数在逻辑上是等价的,并且在一个中表达的任何查询都可以在其他中表达。关系代数和关系演算不支持聚合函数,查询可以在没有聚合函数的情况下用sql表示。

4 个答案:

答案 0 :(得分:4)

这是我的答案。

我在http://www.sqlfiddle.com/#!2/f2fb85/1创建了一个sqlfiddle,所以你可以尝试一下。

查询是:

SELECT p.*
FROM product p
WHERE NOT EXISTS (
    SELECT c.cid
    FROM customer c
    WHERE NOT EXISTS (
        SELECT l.lid
        FROM lineitem l
        JOIN orders o ON o.oid = l.oid
        WHERE l.pid = p.pid
        AND o.cid = c.cid
    )
    AND c.city = 'X'
) AND EXISTS (
    SELECT c.cid
    FROM customer c
    WHERE c.city = 'X' 
)

答案 1 :(得分:1)

根据您的评论,我已将此前的答案替换为不使用IN的答案。这个使用多级相关子查询:

select p.* 
from product p
where exists (
  select *
  from customer c
  where c.city = 'x'
    and exists (
      select *
      from lineitem l
      where l.pid = p.pid
        and exists (
          select *
          from orders o
          where o.oid = l.oid
            and o.cid = c.cid
        )
    )
)
  and not exists(
    select *
    from customer c
    where c.city = 'x'
      and not exists (
        select *
        from lineitem l
        where l.pid = p.pid
          and exists (
            select *
            from orders o
            where o.oid = l.oid
              and o.cid = c.cid
          )
    )
  )

SQL Fiddle here

答案 2 :(得分:1)

ANSI-Sql缺乏集合论universal quantifier,你需要use rewrite roles to get existential quantifier

∀ Universal quantifier (For all . . .)
∃ Existential quantifier (There exists . . .)

示例:

(∀c ∈ CUSTOMER)
⇔ /*Add double negation */
¬¬(∀c ∈ CUSTOMER)
⇔ /*Bring one negation into the quantification, quantifier changes */
¬(∃c ∈ CUSTOMER)

Sql翻译:

SELECT p.*
FROM product p
WHERE NOT EXISTS (
  SELECT c.cid
  FROM customer c
  WHERE  c.city = 'X'
  AND NOT EXISTS
  (
    SELECT o.oid
    FROM orders o
    JOIN lineitem l ON l.oid = o.oid
    WHERE l.pid = p.pid
    AND o.cid = c.cid
  )
)

Fiddle-Demo

答案 3 :(得分:0)

select * from product p where not exists(
    select *
    from customer c
    where c.city = 'x'
      and not exists (
        select *
        from lineitem l
        where l.pid = p.pid
          and exists (
            select *
            from orders o
            where o.oid = l.oid
              and o.cid = c.cid
          )
    )
  )

关系演算:

{T| ∃pЄproduct (¬(∃cЄcustomer(c.city="Newark")^¬(∃lЄlineitem(l.pid=p.pid)^∃oЄorders(o.oid=l.oid^o.cid=c.cid))))}

关系代数:

enter image description here