跨3个表的复杂多连接查询

时间:2012-08-29 21:36:46

标签: php mysql join

我有3张桌子:

shops,PRIMARY KEY cid,zbid
shop_items,PRIMARY KEY id
shop_inventory,PRIMARY KEY id

shops a与以下shop_items b相关:a.cid=b.cid AND a.zbid=b.szbid shopsshop_inventory

没有直接关系

shop_items bshop_inventory c有以下关系:b.cid=c.cid AND b.id=c.iid

现在,我想运行一个返回a.*的查询(shops中的所有列)。那将是:

SELECT a.* FROM shops a WHERE a.cid=1 AND a.zbid!=0

请注意,WHERE子句是必需的。

接下来,我想返回每个商店的商品数量:

SELECT
  a.*,
  COUNT(b.id) items
FROM shops a
LEFT JOIN shop_items b ON b.cid=a.cid AND b.szbid=a.zbid
WHERE a.cid=1
GROUP BY b.szbid,b.cid

正如您所看到的,我为此添加了GROUP BY条款。

接下来,我想返回商店中每件商品的平均价格。这不太难:

SELECT
  a.*,
  COUNT(b.id) items,
  AVG(COALESCE(b.price,0)) average_price
FROM shops a
LEFT JOIN shop_items b ON b.cid=a.cid AND b.szbid=a.zbid
WHERE a.cid=1
GROUP BY b.szbid,b.cid

我的下一个标准是它变得复杂。我还希望为每个商店返回独特的买家。这可以通过查询shop_inventory c,获取COUNT(DISTINCT c.zbid)来完成。现在记住这些表是如何相关的;这应仅针对c中与b中与相应商店a拥有的商品相关的行进行。

我尝试了以下操作:

SELECT
  a.*,
  COUNT(b.id) items,
  AVG(COALESCE(b.price,0)) average_price,
  COUNT(DISTINCT c.zbid)
FROM shops a
LEFT JOIN shop_items b     ON b.cid=a.cid AND b.szbid=a.zbid
LEFT JOIN shop_inventory c ON c.cid=b.cid AND c.iid=b.id
WHERE a.cid=1
GROUP BY b.szbid,b.cid

然而,这不起作用,因为它搞砸了items值。实现这一结果的正确方法是什么?

我还希望能够返回每个商店的购买总数。这可以通过查看shop_inventory c并为每个商店累加c.quantity值来完成。我该如何添加呢?

2 个答案:

答案 0 :(得分:2)

试试这个解决方案:

SELECT    a.*,
          COALESCE(b.item_cnt,  0) AS item_cnt,
          COALESCE(b.avg_price, 0) AS avg_price,
          COALESCE(b.buyer_cnt, 0) AS buyer_cnt
FROM      shops a
LEFT JOIN (
          SELECT    a.cid, 
                    a.szbid, 
                    COUNT(*)     AS item_cnt, 
                    AVG(a.price) AS avg_price,
                    b.buyer_cnt
          FROM      shop_items a
          LEFT JOIN (
                    SELECT   cid,
                             iid,
                             COUNT(DISTINCT zbid) AS buyer_cnt
                    FROM     shop_inventory
                    WHERE    cid = 1
                    GROUP BY cid, 
                             iid
                    ) b ON a.cid = b.cid AND a.id = b.iid
          WHERE     a.cid = 1 AND
                    a.szbid <> 0
          GROUP BY  a.cid,
                    a.szbid
          ) b ON a.cid = b.cid AND a.zbid = b.szbid
WHERE     a.cid = 1 AND 
          a.zbid <> 0

答案 1 :(得分:1)

您可以编写子选择代替COUNT(DISTINCT c.zbid) + LEFT JOIN shop_inventory

SELECT
  a.*,
  COUNT(b.id) items,
  AVG(COALESCE(b.price,0)) average_price,

  ( SELECT COUNT(DISTINCT c.zbid)
    FROM shop_inventory c
    WHERE c.cid=b.cid AND c.iid=b.id
  )

FROM shops a
LEFT JOIN shop_items b     ON b.cid=a.cid AND b.szbid=a.zbid
WHERE a.cid=1
GROUP BY b.szbid,b.cid