简体   繁体   English

带计数和联接表的SQL查询

[英]SQL Query With Count And Joining Table

I have the following three tables: 我有以下三个表:

Customer 顾客
id (PK) id(PK)
name 名称

Product 产品
id(PK) ID(PK)
name 名称
price 价钱

Transaction 交易
id(PK) ID(PK)
customer_id(FK ref Customer.id) customer_id(FK ref Customer.id)
product_id(FK ref Product.id) product_id(FK ref Product.id)
date_created 创建日期

I'm running the following query which gives me the the amount of products used per customer: 我正在运行以下查询,该查询为我提供了每个客户使用的产品数量:

SELECT p.id, p.name, Count(p.id), p.price
FROM transaction t, product p, customer c
WHERE p.id = t.product_id
      AND  c.id = t.customer_id
      AND c.id = 1
group by p.price, p.name, p.id
ORDER BY p.name ASC;

This works, except that it gives me ONLY the products which the customer has used with their respective count. 这行得通,只是它仅向我提供客户使用过的产品及其各自数量。 What I want is the list of ALL the products with a count of 0 for those products which the customer hasn't used. 我想要的是该客户尚未使用的所有产品的清单,计数为0。 I'm having trouble trying to figure this out since I'm using the Transaction table as a joining table between the customers and the products, and the way I'm finding the count of each product per customer is by a count of records (as you can see in the SQL code above). 我很难弄清楚这一点,因为我将“交易”表用作客户和产品之间的联接表,而我发现每个客户的每个产品的数量的方式是通过记录数量(如您在上面的SQL代码中所见)。

I could do: 我可以做:

SELECT *
FROM product
WHERE product.name NOT IN (SELECT p.name
                           FROM transaction t, product p, customer c
                           WHERE p.id = t.product_id
                                 AND  c.id = t.customer_id
                                 AND c.id = 1);

and then somehow programmatically assign 0 to the count in my resultset, but then I'll end up with two lists, one that contains the name of the product, the count of each product, and the price per product that the customer has used , and another list that will contain all the product names, a count of 0, and the price for each product that the customer has not used . 然后以编程方式将0分配给我的结果集中的计数,但是最后我得到两个列表,其中一个包含产品名称,每个产品的数量以及客户使用过的每个产品的价格,另一个包含所有产品名称,计数为0以及客户未使用的每种产品的价格的列表。

This could be a solution, but it seems far from practical since id be dealing with two list and having to programmatically assign values instead of dealing with one list that would contain all the data that I need, which would affect ordering, etc. 这可能是一个解决方案,但是似乎不切实际,因为id只能处理两个列表,并且必须以编程方式分配值,而不是处理一个包含我需要的所有数据的列表,这会影响排序等。

I'm wondering if this is possible or if there's another way to look at this problem. 我想知道这是否可行,或者是否有另一种方式来解决这个问题。

I hope this is clear enough. 我希望这足够清楚。 I'd appreciate any insight into this! 我将不胜感激!

Mauricio B. 毛里西奥(Mauricio B.)

This should work in most DBMS. 这应该适用于大多数DBMS。 It groups the transaction table for all the customers products and gets their count. 它将所有客户产品的交易表分组,并获得他们的数量。 This is then left joined to the products. 然后将其加入产品。 As it is a left join, all products will be included. 由于是左联接,因此将包括所有产品。 For those products the customer hasn't used the joined columns will be NULL . 对于那些尚未使用的客户,连接的列将为NULL So will be the count. 因此将是计数。 With the coalesce() function returning the first argument not null, we get 0 as count for those and the actual count for the others. 使用coalesce()函数返回的第一个参数不为null时,我们得到的计数为0,其他计数为实际计数。 If your actual DBMS doesn't support coalesce() you might have to replace that with the respective DBMS specific function. 如果您的实际DBMS不支持coalesce() ,则可能必须将其替换为各自的DBMS特定功能。

SELECT p.id,
       p.name,
       coalesce(t.count, 0) count,
       p.price
       FROM product p
            LEFT JOIN (SELECT t.product_id,
                              count(*) count
                              FROM transaction t
                              WHERE t.customer_id = 1
                              GROUP BY t.product_id) t
                      ON t.product_id = p.id
       ORDER BY p.name ASC;

Never use commas in the FROM clause. 请勿FROM子句中使用逗号。 Always use proper, explicit, standard JOIN syntax. 始终使用正确,明确,标准的JOIN语法。

Your problem is specifically that you need a left join : 您的问题特别是您需要left join

select p.id, p.name, Count(t.id), p.price
from product p left join
     transaction t
     on p.id = t.product_id and
        t.customer_id = 1
group by p.price, p.name, p.id
order by p.name asc;

Note: you do not need the customer table. 注意:您不需要客户表。 The id is in the transaction table. 该ID在交易表中。

You have to do two select queries and join them: 您必须执行两个选择查询并将它们加入:

select prodcust.custname, prodcust.prodname, prodcust.prodId, 
    isnull(tranCount,0) as count, prodcust.price 
from
(
    select p.name as prodname, p.id as prodID, c.name as custname, c.id as 
        custid, p.price 
    from product p, customer c
)
as prodcust

left join 

(
    select p.price, p.id, c.id as custid, count(t.id) as tranCount
    from Transaction t
    inner join customer c
       on c.id = t.customer_id
    inner join product p
       on t.product_id = p.id
    group by p.price, p.id, c.id
) as trans 
on prodcust.custid = trans.custid
   and prodcust.prodID = trans.id
order by custname, prodname

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM