简体   繁体   English

连接中不存在的行的 SQL 聚合函数

[英]SQL aggregate function for non existing rows in joins

I am trying to find a SQL Get aggregate as 0 for non existing row using joins for the below tables for a certain year.我试图找到一个 SQL Get 聚合为 0 的非现有行,在某一年使用下表的连接。

Customers -> customerid, Name
product -> prodcutid, price, name
Sales -> productid,customerid,date, orders
create table product(productid int,name char(20), price int,PRIMARY KEY(productid));
create table Customers(customerid int,name char(20),PRIMARY KEY(customerid));
create table sale(productid int,customerid int,orders int, date date);

INSERT INTO product (productid,name ,price) 
VALUES (1, 'TV', 3200);

INSERT INTO product (productid,name ,price) 
VALUES (2, 'fridge', 4200);

INSERT INTO Customers (customerid,name) 
VALUES (1, 'US');

INSERT INTO Customers (customerid,name) 
VALUES (2, 'Aus');

INSERT INTO sale (productid,customerid,orders,date) 
VALUES (2, 2, 1,'2018-10-2');

INSERT INTO sale (productid,customerid,orders,date) 
VALUES (1, 2, 10,'2018-10-13');

INSERT INTO sale (productid,customerid,orders,date) 
VALUES (1, 1, 100,'2018-10-2');

INSERT INTO sale (productid,customerid,orders,date) 
VALUES (1, 1, 100,'2019-10-1');

I have got this query to find the aggregation for existing order for a products for a certain year but i also wanted to get the products which were not ordered during the same year as others:我有这个查询来查找某一年产品的现有订单的聚合,但我也想获得与其他产品在同一年未订购的产品:

  with cte as (select producid,customerid,sum(orders) as s from sales 
  where date_part('year', date) = 2018
  group by productid,customerid)
  select a.name,b.name,(c.s * b.price) as sales
  from customers as a 
  join cte as c on a.prodcutid=c.productid
  join product as b on b.customerid=c.customerid; 

Data what i am able to get with above query:我可以通过上述查询获得的数据:

 -----------------------------------------------
 Product.name | Customer.name | Total_sale Value
 -----------------------------------------------
      TV       |   AUS        |  32000 (orders * price per product) 
      Fridge   |   AUS        |  4200 
      TV       |   US         |  320,000 

Data what i want is for the year 2018:我想要的是 2018 年的数据:

 -----------------------------------------------
 Product.name | Customer.name | Total_sale Value
 -----------------------------------------------
      TV       |   AUS        |  32000 (orders * price per product) (if there was a sale then you should get a value else then it should be 0)
      Fridge   |   AUS        |  4200 
      Fridge   |   US         |  0 (as Customer US didnt order fridge at all)
      TV       |   US         |  320,000 

I tried following the same solution provided SQL Get aggregate as 0 for non existing row using inner joins but couldn't get the answer, forgive me for the duplicate but please let me know what i did wrong.我尝试遵循相同的解决方案,为使用内部联接的非现有行提供SQL 获取聚合为 0,但无法得到答案,请原谅我的重复,但请让我知道我做错了什么。 I am new to sql so please forgive me for duplicates.我是 sql 新手,所以请原谅我重复。

Note: the question has been edited since this answer was posted and I'm no longer 100% sure what is being asked注意:自从发布此答案以来,该问题已被编辑,我不再 100% 确定所问的是什么

I am trying to find a SQL Get aggregate as 0 for non existing row using joins我正在尝试使用连接为非现有行找到 SQL Get 聚合为 0

Conceptually, the sales table relates products with customers从概念上讲,销售表将产品客户联系起来

  • There is a product, and there always is a product (because you're looking at this as if "i am interested in every product and whether it sold or not")有产品,总有产品(因为你看这个好像“我对每个产品都感兴趣,不管它是否出售”)

  • There is perhaps a customer (if they registered and never bought anything they could be a customer with no sales)可能有一个客户(如果他们注册了但从未购买过任何东西,他们可能是一个没有销售的客户)

  • And there is a sale only if a product has been bought by a customer (so customers that never bought anything aren't mentioned in sales, and we're only interested in products that have or haven't sold)并且只有在客户购买了产品时才会有销售(因此从未购买过任何产品的客户不会在销售中提及,我们只对已售出或未售出的产品感兴趣)

So your relation graph to answer your question needs to look like:所以你的关系图来回答你的问题需要看起来像:

products -> sales -> customer

The products -> sales relation will break if a product has never been ordered, so it needs to be a LEFT JOIN to keep all the products and associates sales with products only if matching sales exist.如果从未订购过产品,则products -> sales关系将中断,因此需要使用 LEFT JOIN 来保留所有产品,并且仅当存在匹配的销售时才将销售与产品相关联。

The sales -> customer shouldn't break and can be INNER JOIN (if you're willing to join it first) or LEFT JOIN if you don't do it as a subquery (if you make it immer join, any sales that are null because the product has never sold will not match to a customer so the unsold product will disappear from the results sales -> customer不应该中断并且可以是 INNER JOIN(如果您愿意先加入)或 LEFT JOIN 如果您不将其作为子查询进行(如果您使它成为 immer join,任何销售是null 因为该产品从未售出将与客户不匹配所以未售出的产品将从结果中消失

As such, you need a query like:因此,您需要这样的查询:

SELECT ...
FROM
  products p
  LEFT JOIN sales s ON ...
  LEFT JOIN customer c ON ...

Or you need或者你需要

SELECT ...
FROM
  products p
  LEFT JOIN 
  (SELECT * FROM sales s INNER JOIN customer c ON ...) sc

It might be simpler if you use the second form and perform the grouping inside the subquery, but it's trivial to do these anywhere如果您使用第二种形式并在子查询中执行分组可能会更简单,但在任何地方执行这些操作都很简单

The nulls introduced for no-sales against products that never sold will participate in SUM/AVG etc as if they were 0为从未销售过的产品的无销售引入的空值将参与 SUM/AVG 等,就好像它们是 0


Side note, I'm not really sure what bearing the customer table has on any of your stated requirements, and it can probably be omitted旁注,我不确定客户表对您陈述的任何要求有什么轴承,并且可能可以省略

with cte as (
    select productid, customerid, sum(orders) as s from sale
    where year(date) = 2018
    group by productid, customerid
)
select p.name, c.name, coalesce(s.s * p.price, 0) as sales
from product as p
    cross join customer as c
    left outer join cte as s on s.productid = p.productid
                           and s.customerid = c.customerid

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

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