【问题标题】:LEFT OUTER JOIN conditions for two queries?两个查询的左外连接条件?
【发布时间】:2014-07-24 18:27:59
【问题描述】:

我有以下两个查询来查找从 2014 年 1 月开始的每周的综合浏览量和订单。

select productid,
EXTRACT (week from dt)as WEEK,
count(productid)as PageViews
from PageView
where client = 'XYZ'
and dt between '2014-06-01' and '2014-06-30'
GROUP BY WEEK, productid
ORDER BY WEEK asc;

和

select
count(distinct t.orderid),
EXTRACT(week from t.dt) AS WEEK
FROM Transaction t
where t.client = 'XYZ'
and t.dt between '2014-01-01' AND '2014-06-30'
GROUP BY WEEK
ORDER BY WEEK asc;

为了获得正确的数据,我需要创建一个与 Transaction 和 PageView Tables 中的周匹配的连接条件,例如来自 Transaction 的周 = 来自 PageView 的周。然而,我不知道它的语法是什么样的。

做一个简单的

PageView pv LEFT OUTER JOIN Transaction t
ON pv.productid = t.productid 
AND EXTRACT(week from t.dt) = EXTRACT(week from pv.dt) 

没有给出正确的输出(即网页浏览量和订单量显着增加)。有人可以解释一下如何将这两个查询结合起来获得所需的输出,即 PageView 表中的所有产品和按周分组的 Transaction 表中的相应订单

【问题讨论】:

  • pageview和trans table有关系吗?
  • 两个表的主键是什么?两个表都存在哪些备用键(如果有)?

标签: sql database postgresql


【解决方案1】:
select week, pid, pageviews, orders
from
    (
        select
            date_trunc('week', dt) as week,
            productid as pid,
            count(productid) as pageviews
        from pageview
        where client = 'XYZ' and dt between '2014-06-01' and '2014-06-30'
        group by 1, 2
    ) pv
    full outer join
    (
        select
            date_trunc('week', dt) as week,
            product_id as pid,
            count(orderid) as orders
        from transaction
        where client = 'XYZ' and dt between '2014-01-01' and '2014-06-30'
        group by 1, 2
    ) t using (week, pid)
order by 1, 2

【讨论】:

  • 为什么是full outer join?只是想理解。
  • @Rahul 是否可以在没有查看特定产品 ID 的情况下获得订单?问题中并不清楚。如果答案是否定的,那么只需将full outer 更改为left 尽管full 将正常工作,只是存在刨床找不到最佳计划的风险。
  • @ClodoaldoNeto 谢谢,这似乎工作得很好。然而 date_trunc 给出了一个完整的日期和时间戳,而不仅仅是周数。我想我应该在问题中提到这一点。 EXTRACT(week from dt) as WEEK 是更好的选择吗?
  • @AshwinSingh extract(week) 在大约一年或一年以上的时间段内将是错误的。并且会在涉及新年的期间错误地排序。否则没关系
  • @ClodoaldoNeto 还有一件事,如果我想为 n 个客户端运行此查询,是否只需在两个选择语句中添加 select client_name ?
【解决方案2】:

我认为问题出在ON pv.productid = t.productid AND EXTRACT(week from t.dt) = EXTRACT(week from pv.dt)

这不能是左连接。 PV 和 T 之间的 ID 可能匹配,但在某些情况下周可能为空。所以 AND 会消除左连接。

因此,您只需先加入 ID,就可以得到笛卡尔坐标。然后,您需要过滤掉不匹配的周,但保留 T.Null 值。但是它假定 t.dt 不能为空,如果它可以为空,则计数可能仍会关闭,具体取决于您想要的方式处理事务表日期中的空值。

此外,您可能需要使用内联视图(但我认为这是矫枉过正)

SELECT * 
FROM
(select productid,
  EXTRACT (week from dt)as WEEK,
  count(productid)as PageViews
  from PageView
  where client = 'XYZ'
  and dt between '2014-06-01' and '2014-06-30'
  GROUP BY WEEK, productid) PV
LEFT JOIN (
  SELECT
  count(distinct t.orderid),
  EXTRACT(week from t.dt) AS WEEK
  FROM Transaction t
  where t.client = 'XYZ'
  and t.dt between '2014-01-01' AND '2014-06-30'
  GROUP BY WEEK) T
ON pv.productid = t.productid  --The gold is in this and the next line
WHERE (T.Week = PV.Week OR T.Week is null)  --don't forget this one.

我认为这行不通... 开启(PV.ProductID=T.productID 和 T.Week=PV.Week) 或(PV.ProductID = T.ProductID AND T.Week 为空)

因为尚未生成笛卡尔坐标系,因此尚未评估 T.Week。这就是为什么我认为它属于 where。

【讨论】:

  • 想必这些表还必须加入客户 ID 或订单 ID?
  • 是的,没错,但我认为你应该删除 PV.Week = T.Week
  • 不确定为什么要删除查询?对我来说是正确的。
  • 这使它成为一个内部连接!我试过了,但它消除了一些只存在于 PageView 表中的产品。
  • 我想你想要 where 子句。
猜你喜欢
  • 2012-10-25
  • 1970-01-01
  • 2020-06-12
  • 2015-02-06
  • 2011-03-12
  • 1970-01-01
  • 2019-06-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多