Sql 按时段分组联接,完全联接未按预期工作

Sql 按时段分组联接,完全联接未按预期工作,sql,postgresql,Sql,Postgresql,我有一张销售表: SALES |---------|-------------|-------------| | order | ammount | date | |---------|-------------|-------------| | 001 | $2,000 | 2018-01-01 | | 002 | $3,000 | 2018-01-01 | | 003 | $1,500 | 2018-01-0

我有一张销售表:

SALES
|---------|-------------|-------------|
|  order  |   ammount   |  date       |
|---------|-------------|-------------|
|  001    | $2,000      | 2018-01-01  |
|  002    | $3,000      | 2018-01-01  |
|  003    | $1,500      | 2018-01-03  |
|  004    | $1,700      | 2018-01-04  |
|  005    | $1,800      | 2018-01-09  |
|  006    | $4,200      | 2018-01-11  |
|---------|-------------|-------------|
另外,我有一个表格,根据任意时间段对销售额进行分组:

BUDGET PERIODS
|---------|-------------|--------------|
| ID      | start_date  | end_date     |
|---------|-------------|--------------|
| 1       | 2018-01-01  | 2018-01-02   | <- notice this is a 2 day period...
| 2       | 2018-01-03  | 2018-01-05   | <-- but this is 3 days
|---------|-------------|--------------|
我通过这样一个查询完成了它:

SELECT
    bp.start_date,
    bp.end_date,
    SUM(s.ammount)
FROM
    budget_periods bp
LEFT JOIN 
    sales s ON s.date >= bp.start_date AND s.date <= bp.end_date
GROUP BY 
    start_date, 
    end_date
请注意,如果同时将2018-01-09和2018-01-11截短为一周,则显示2018-01-08。要计算我的结束日期,预算期“默认”为七天,因此比开始日期晚六天

因此,我将查询修改为完全联接,如下所示:

GROUPED SALES
|--------------|---------------|-----------------|
| start_date   | end_date      | ammount         |
|--------------|---------------|-----------------|
| 2018-01-01   | 2018-01-02    | $5,000          |
| 2018-01-03   | 2018-01-05    | $3,200          |
|--------------|---------------|-----------------|
SELECT
    COALESCE(bp.start_date, DATE_TRUNC('WEEK', s.date)) AS new_start_date,
    COALESCE(bp.end_date, DATE_TRUNC('WEEK', s.date) + INTERVAL '6 DAY') AS new_end_date,
    SUM(s.ammount)
FROM
    budget_periods bp
FULL JOIN 
    sales s ON s.date >= bp.start_date AND s.date <= bp.end_date
GROUP BY 
    new_start_date, 
    new_end_date
选择
合并(bp.start\u date,date\u TRUNC('WEEK',s.date')作为新的开始日期,
合并(bp.end_date,date_TRUNC('WEEK',s.date)+INTERVAL'6 DAY')作为新的_end_date,
总数(s.ammont)
从…起
预算期间
完全联接
sales s ON s.date>=bp.start_date和s.date如果希望sales中的所有行,则将其作为
左联接中的第一个表。但是,我认为
完全连接
应该可以工作,就像这个
左连接一样:

SELECT COALESCE(bp.start_date, DATE_TRUNC('WEEK', s.date)) as new_start_date,
       COALESCE(bp.end_date, DATE_TRUNC('WEEK', s.date) + interval '6 day') as new_end_date,
       SUM(s.amount)
FROM sales s LEFT JOIN
     budget_periods bp
     ON s.date >= bp.start_date AND s.date <= bp.end_date
GROUP BY new_start_date, new_end_date;
选择合并(bp.start\u日期,date\u TRUNC('WEEK',s.date))作为新的开始日期,
合并(bp.end_date,date_TRUNC('WEEK',s.date)+interval'6 day')作为新的_end_date,
金额
从销售人员的左连接
预算期间

然而,在s.date>=bp.start_date和s.date上,我有一个WHERE子句。为了减少复杂性,我没有考虑这个问题。我只是认为这不相关。在更接近现实的版本中,我的sales表有另一列显示“store”,我只需要包括某些商店,因此我的查询有一个
其中s.store In('store1','store2')
,但检查数据时,这个商店排除过滤器并不是我的其他销售没有出现的原因,因为过滤器不适用于它们。@JDGamboa。过滤器与您看到的行为完全相关。问另一个问题。顺便说一句,如果你能提供一个工作示例,那就太好了:将
FULL JOIN
更改为
RIGHT JOIN
会得到预期的结果:@Abelisto。多聪明啊。令我惊讶的是
WITH
语句解决了
右连接的问题,但数据库中已经存储了表的情况并非如此。它还禁止使用带有我以前从未遇到过的错误的
完全联接。
SELECT COALESCE(bp.start_date, DATE_TRUNC('WEEK', s.date)) as new_start_date,
       COALESCE(bp.end_date, DATE_TRUNC('WEEK', s.date) + interval '6 day') as new_end_date,
       SUM(s.amount)
FROM sales s LEFT JOIN
     budget_periods bp
     ON s.date >= bp.start_date AND s.date <= bp.end_date
GROUP BY new_start_date, new_end_date;