2017-07-17 180 views
1

我有表的集合在关系数据库SQL - 计数与嵌套子查询

  • products
  • categories
  • orders
  • line_items
  • customers

产品与类别具有多对多关系(连接表categories_products),并且也具有并属于许多ordersline_items,这是productsorders的连接表,带有一个id。 A customer也有很多orders

我试图把一些SQL,这将使我这种反应:

customer_id | customer_first_name | category_id | category_name | number_purchased 
    ----------------------------------- 
    1 |Jack | 1 | Electronics | 15 
    2 |Jill | 1 | Electronics | 2 
    2 |Jill | 2 | Hiking | 3 

这是SQL的巨厚片我一直在试图用它来获取这些值:

SELECT 
      DISTINCT customers.id AS customer_id, 
      customers.first_name AS customer_first_name, 
      categories.id AS category_id, 
      categories.name AS category_name, 
      (
       SELECT count(li.id) FROM line_items li 
       INNER JOIN orders o ON li.order_id = o.id 
       INNER JOIN products p ON li.product_id = p.id 
       INNER JOIN categories_products cp ON cp.product_id = p.id 
       WHERE 
        o.customer_id = customer_id 
        AND o.status = 3 
        AND cp.category_id = category_id 
      ) AS number_purchased 
     FROM orders 
     LEFT JOIN customers ON orders.customer_id = customers.id 
     LEFT JOIN line_items li ON li.order_id = orders.id 
     LEFT JOIN products ON products.id = li.product_id 
     LEFT JOIN categories_products catpr ON catpr.product_id = products.id 
     LEFT JOIN categories ON catpr.category_id = categories.id 

只有计数本身是错误的。而不是获取客户在特定类别中购买的订单项数量,而是对所有已完成订单的LineItem进行计数。

如何才能让计数正确地代表customercategory内购买的line_items的数量?

注意:在SQL文本中,o.status = 3正在使用枚举来指示订单是“完整的”。

+0

你的查询看起来像它特定于类别。将删除'number_purchased'返回一个类似的输出? –

+0

我建议通过添加分组 –

+0

@RudyM'number_purchased'是唯一返回不正确的值。理论上我可以在每个'customer'和'category'的每个组合或代码级别的单独查询中获得'number_purchased'值,但是我特别试图编写单个SQL语句来正确输出所有这些信息 – PapaPoison

回答

0

我认为你的内心加入categories_products是搞砸了。你应该设置一个小提琴,像@Strawberry建议的那样,或者试试这个:

SELECT 
     DISTINCT customers.id AS customer_id, 
     customers.first_name AS customer_first_name, 
     categories.id AS category_id, 
     categories.name AS category_name, 
     (
      SELECT count(li.id) FROM line_items li 
      INNER JOIN orders o ON li.order_id = o.id 
      INNER JOIN products p ON li.product_id = p.id 
      WHERE 
       o.customer_id = customer_id 
       AND o.status = 3 
     ) AS number_purchased 
    FROM orders 
    LEFT JOIN customers ON orders.customer_id = customers.id 
    LEFT JOIN line_items li ON li.order_id = orders.id 
    LEFT JOIN products ON products.id = li.product_id 
    LEFT JOIN categories_products catpr ON catpr.product_id = products.id 
    LEFT JOIN categories ON catpr.category_id = categories.id 
+1

好的,这个评论让我大部分时间都在那里。一个额外的细节,帮助它完全正确的是,在我使用'customer_id'的子查询中。用原来的'customers.id'代替,确保将正确的值传递给子查询。 – PapaPoison

0

如果你想纠正你的计数,我会建议在子查询中使用GROUP BY子句。如果您使用GROUP BY命令,那么只有在查看用户标识正确时才能获取您检索的特定订单。我鼓励你看看你的SQL代码的其他部分的错误来清理这个庞大的查询。例如,确保你想要使用不同的,并且你实际上想要使用左连接和内连接,这两者都可能严重影响程序的性能。

+0

当你说GROUP BY命令时,你是什么意思? 我向子查询添加了一个GROUP BY语句('GROUP BY o。id'),这会使_first_计数正确,但每个后续行都错误地使用相同的计数。 例如,'customer1'的订单中有3个'line_items' /'products','category'为'Electronics'。对于第一行,“number_purchased”列计为3 - 正确。然而,'customer2'有一个包含2个'line_items' /'products'的订单,并且'category'为'Books'。当伯爵应该是2时,伯爵仍然回到3点。那里有什么见解? – PapaPoison