在SQL中构建嵌套查询

时间:2015-11-30 20:12:29

标签: sql

我是SQL的新手,无法构建查询:

我有三张桌子:

杂志店的顾客:

Customer(cid, name)

杂志

Magazine(mid, topic)

杂志的订阅:

Subscribes(cid, mid)

如何构建一个查询,以显示仅订阅一本杂志的客户,条件是所有其他订阅该杂志的客户都订阅了至少一本其他杂志?

我设法构建了一个查询(不确定是否绝对正确),该查询显示只订阅了一本杂志并且卡在此处的客户:

select customer.cid, customer.name, count(subscribes.mid)
from subscribes, customer
where subscribes.cid=customer.cid 

group by customer.cid
having count(subscribes.mid)=1

4 个答案:

答案 0 :(得分:3)

  

如何构建一个查询,向我展示客户   订阅了只有一本杂志,条件是其他所有   订阅该杂志的客户至少订阅了一个   其他杂志?

你有正确的想法一步一步地采取它。

客户只订阅了一本杂志

 SELECT cid
 FROM subscribes
 GROUP BY cid
 HAVING COUNT(mid) = 1

客户订阅了两本或更多杂志

SELECT cid
FROM subscribes
GROUP BY cid 
HAVING COUNT(mid) > 1

客户及他们订阅的杂志数量

SELECT cid, count(mid) as s_count
FROM subscribes
GROUP BY cid

所以

WITH cust_and_count AS
(
  SELECT cid, count(mid) as s_count
  FROM subscribes
  GROUP BY cid
)
SELECT cust_and_count.cid, s1.mid
FROM cust_and_count -- with the where below this gives us all users subscribed to a single mag
-- Get the magazine of users that have one subscription
JOIN subscribes s1 on cust_and_count.cid = s1.cid
-- Join that magazine back to who subscribes exclude our starting guys
JOIN subscribes s2 on s1.mid = s2.mid and s2.cid != cust_and_count.cid
-- Join back to our counts and make sure it is greater than 1
JOIN cust_and_count c2 on s2.cid = c2.cid and c2.s_count > 1
WHERE cust_and_count.s_count = 1
  

请注意,表名通常不是复数 - 所有表都有行,您通常会根据单个元素的名称来命名,所以客户,杂志,订阅都在您的情况下。

答案 1 :(得分:1)

以下查询选择仅订阅1本杂志的所有客户:

//equivalent to assembly
//MOV EAX sys_call_no
//INT 0x80
void* interrupt(int service, void* args, void* ret)
{
   kernel::intr_queue.push_back_syncd(interrupt_context(){kernel::int_vector[service], args, ret});
   waitForServiceCompleted();
   return ret;
}
//in kernel thread
while(true)
{
  while(!intr_queue.isEmpty())
  {
    auto context = intr_queue.pop();
    context.ret = context.func(context.args);
    notifyDone();
  }
}

此查询选择SELECT * FROM Subscribes GROUP BY cid HAVING COUNT(Subscribes.mid) = 1 杂志C以外的所有客户,只有1个订阅:

M

我相信,这会做你在问题中提出的问题:

SELECT 1
FROM Subscribes
WHERE mid = M
      AND cid != C
      AND EXISTS (SELECT 1
                  FROM Subscribes
                  WHERE cid = Subscribes.cid
                  AND COUNT(mid) <= 1)

说明:

SELECT *
FROM Subscribes
GROUP BY cid
HAVING COUNT(Subscribes.mid) = 1 as SingleSubs
       AND NOT EXISTS (SELECT 1
                       FROM Subscribes
                       WHERE mid = SingleSubs.mid
                             AND cid != SingleSubs.cid
                             AND EXISTS (SELECT 1
                                         FROM Subscribes
                                         WHERE cid = Subscribes.cid
                                         AND COUNT(mid) <= 1))

答案 2 :(得分:0)

必须归功于@Hogan ......

小提琴:

http://sqlfiddle.com/#!6/860e7/4

代码:

;WITH cust_and_count AS
(
  SELECT cid, count(mid) as s_count
  FROM subs
  GROUP BY cid
)
SELECT distinct c1.cid
FROM cust_and_count c1
JOIN subs s1 on c1.cid = s1.cid
JOIN subs s2 on s1.mid = s2.mid and s2.cid != c1.cid and s1.mid >1
WHERE c1.s_count = 1

答案 3 :(得分:0)

如果问题正确,那么答案是:

select cid from subscribers
group by cid
having count(mid) = 1

,因为:

  

如何构建一个显示客户的查询   订阅了只有一本杂志,条件是其他所有   订阅该杂志的客户至少订阅了   另一本杂志?

查询返回仅订阅1个杂志的订阅者。您的第二个条件会自动应用,因为其他客户将处于结果集中。即如果其他客户订阅了输出中的某个杂志而该客户没有输出,这意味着他订阅了更多的杂志,包括当前的杂志。

如果您想用同一杂志排除成对客户,请:

select max(cid)
from(select cid, max(mid) mid from subs
     group by cid
     having count(mid) = 1) t
group by mid
having count(cid) = 1