Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL连接两个具有不同详细级别的表_Sql_Postgresql - Fatal编程技术网

SQL连接两个具有不同详细级别的表

SQL连接两个具有不同详细级别的表,sql,postgresql,Sql,Postgresql,所以我有两张销售表,预算表和实际表 “预算”有两列:地点和销售。比如说, 定位销售 24$20000 36$100300 40美元24700 共计145 000美元 “实际”有三列:发票号、位置和销售额。比如说, 发票位置销售 10000 36$5000 10001 40$6000 10002 99$7000 等等 共计11万美元 总之,“实际”记录发票级别的交易,而“预算”仅在地点级别进行(无单独发票) 我试图创建一个汇总表,按位置分组,并列列出实际销售额和预算销售额。实际列的总额应为1100

所以我有两张销售表,预算表和实际表

“预算”有两列:地点和销售。比如说,

定位销售
24$20000
36$100300
40美元24700
共计145 000美元

“实际”有三列:发票号、位置和销售额。比如说,

发票位置销售
10000 36$5000
10001 40$6000
10002 99$7000
等等
共计11万美元

总之,“实际”记录发票级别的交易,而“预算”仅在地点级别进行(无单独发票)

我试图创建一个汇总表,按位置分组,并列列出实际销售额和预算销售额。实际列的总额应为110000美元,预算为145000美元。这是我的尝试(在pgAdmin/postgresql上):

我使用左连接是因为“实际”有“预算”没有的位置(例如位置99)

最后,我在实际销售和预算销售两栏都得到了巨大的数字(百万美元),远远超过了实际销售总额(110000美元)或预算销售总额(145000美元)

这是因为我编写查询的方式基本上是要求SQL将“实际”中的每个发票连接到“预算”中的每一行,因此会重复很多次?如果是这样的话,我应该怎么写


提前谢谢

我觉得这个问题很好。然而,很难找出为什么这些数字是错误的。我的建议是,您将预算和实际的按位置分别汇总到两个临时表中,然后使用左联接将它们组合在一起。

是的,您将为每个实际销售行加入一次预算。但是,除非同一地点有多个预算行,否则您的实际销售总额不应该更大。你应该检查一下,因为听起来不应该有

在这种情况下,您需要首先在CTE或子查询中对实际销售额求和,然后将结果加入预算。这样,每个位置只有一行。这就是实际销售额。如果一个位置的预算也确实有多行,那么可能还需要以相同的方式子查询预算

Select Act.Location, Act.actual_sales, budget.sales as budget_sales
From
(
SELECT actual.location, SUM(actual.sales) AS actual_sales
FROM actual
GROUP BY actual.location
) Act
left join budget on Act.location = budget.location 

根据您的描述,两个表中似乎都有重复项。解决这个问题有多种方法。下面是一个使用
union-all
group-by

select Location, 
       sum(actual_sales) as actual_sales,
       sum(budget_sales) as budget_sales
from ((select a.location, a.sales as actual_sales, null as budget_sales
       from actual a
      ) union all
      (select b.location, null, b.sales
       from budget b
      )
     ) ab
group by location;

这种结构保证每个值只计算一次,而不考虑表。

Gordon的建议很好,使用
语句的替代方法是:

WITH aloc AS (
  SELECT location, SUM(sales) FROM actual GROUP BY 1
), bloc AS (
  SELECT location, SUM(sales) FROM budget GROUP BY 1
)
SELECT location, a.sum AS actual_sales, b.sum AS budget_sales
FROM aloc a LEFT JOIN bloc b USING (location)
这相当于:

SELECT location, a.sum AS actual_sales, b.sum AS budget_sales
FROM (SELECT location, SUM(sales) FROM actual GROUP BY 1) a LEFT JOIN
     (SELECT location, SUM(sales) FROM budget GROUP BY 1) b USING (location)
但我发现
中的
语句更具可读性


子查询的目的是使表进入一种状态,其中一行表示相关的内容,即
aloc
在每个位置包含一行,从而使联接的计算结果符合您的要求。

请回答您的问题,并根据该数据添加一些内容和预期输出。请(您的问题-请勿在评论中发布代码或附加信息)请向我们展示一些示例数据。您的查询本身没有问题,但查看您的数据和预期输出确实会有所帮助。此解决方案不起作用,因为您可能在cero sales的某个位置有预算,此记录将被忽略。最好执行union all来计算所有可能的位置;当然,如果您想要其他组合,您可以自由地对这些组合重新排序或使用
FULL
外部联接…
SELECT location, a.sum AS actual_sales, b.sum AS budget_sales
FROM (SELECT location, SUM(sales) FROM actual GROUP BY 1) a LEFT JOIN
     (SELECT location, SUM(sales) FROM budget GROUP BY 1) b USING (location)