如何将两个JOINS正确合并在一起?

时间:2019-11-06 00:26:10

标签: mysql sql database

让我们假设我有产品,并且保存与它们相关的视图和销售。 现在,我想获取特定产品的每日观看次数和销售量。 每天可能没有产品的浏览量或销售量。

  • 产品:product_id
  • 视图:view_id,product_id,已创建
  • 销售:sale_id,product_id,已创建
SELECT products.product_id,
    COALESCE(views.sum,0) AS total_views,
    COALESCE(sales.sum,0) AS total_sales,
    views.day
FROM products
    LEFT JOIN (
            SELECT COUNT(*) AS sum, product_id, date(created) as day
            FROM views
            GROUP BY product_id, day
        ) AS views
        ON views.product_id = products.product_id
    LEFT JOIN (
            SELECT COUNT(*) AS sum, product_id, date(created) as day
            FROM sales
            GROUP BY product_id, day
        ) AS sales
        ON sales.product_id = products.product_id
WHERE products.product_id = 15041
GROUP BY views.day, sales.day

此操作每天返回多行而不是一行,我认为问题是我无法弄清楚如何正确地将JOINS连接在一起。

如何解决使此查询按预期工作?建议进一步优化吗?

输出(错误):

product_id  total_views total_sales day
15041   23  19  2019-11-03
15041   23  37  2019-11-03
15041   57  19  2019-11-04
15041   57  37  2019-11-04
15041   70  19  2019-11-05
15041   70  37  2019-11-05

正确的输出为:

product_id  total_views total_sales day
15041   23  0   2019-11-03
15041   57  19  2019-11-04
15041   70  37  2019-11-05

用户“ METAL”输出:

product_id  total_views total_sales day
15041   1   0   2019-11-03
15041   1   1   2019-11-04
15041   1   1   2019-11-05

2 个答案:

答案 0 :(得分:1)

假设您的产品具有浏览量或销售量,我建议:

select product_id, sum(views) as views, sum(sales) as sales
from ((select product_id, date(created) as day, count(*) as views, 0 as sales
       from views
       where product_id = 15041
       group by product_id, date(created)
      ) union all
      (select product_id, date(created) as day, 0 as views, count(*) as sales
       from sales
       where product_id = 15041
       group by product_id, date(created)
      )
     ) vs
group by product_id, day;

我怀疑left join表中的products确实必要

答案 1 :(得分:0)

在您的UNIONjoin表上尝试使用sales代替views

select p.product_id, 
    , coalesce(sum(case when t1.col = 'views' then ct else 0 end), 0) as total_views
    , coalesce(sum(case when t1.col = 'sales' then ct else 0 end), 0) as total_sales
    , t1.dt
from products p
left join
    (select count(1) as ct, product_id, date(created) dt, 'sales' as col 
        from sales group by date(created), product_id
    union 
    select count(1) as ct, product_id, date(created), 'views' 
        from views group by date(created), product_id) t1 on t1.product_id = p.product_id
group by p.product_id, t1.dt