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_Sum_Aggregate Functions_Subtraction - Fatal编程技术网

Sql 减去不同表的两列

Sql 减去不同表的两列,sql,postgresql,sum,aggregate-functions,subtraction,Sql,Postgresql,Sum,Aggregate Functions,Subtraction,我有两个不相关的表: contribution(id,amount, create_at, user_id) solicitude(id, amount, create_at, status_id, type_id, user_id) 我需要减去用户的贡献和关心的总和,但结果不能是负数 我该怎么做?功能还是查询? 我尝试了以下查询: SELECT sum(contribution.amount) - (SELECT sum(solicitude.amount) FROM solic

我有两个不相关的表:

contribution(id,amount, create_at, user_id)

solicitude(id, amount, create_at, status_id, type_id, user_id)
我需要减去用户的贡献和关心的总和,但结果不能是负数

我该怎么做?功能还是查询?
我尝试了以下查询:

SELECT  sum(contribution.amount)
- (SELECT sum(solicitude.amount) 
   FROM solicitude 
   WHERE user_id = 1 AND status_id = 1) as total
FROM contribution 
WHERE contribution.user_id = 1

你必须加入表格

SELECT sum(c.amount) - s.total 
FROM contribution c inner join  (SELECT user_id, sum(solicitude.amount) total
FROM solicitude  GROUP BY c.user_id HAVING user_id = 1 AND status_id = 1  )s
on c.user_id=s.user_id GROUP BY c.user_id,s.total HAVING c.user_id = 1 

编辑:我忘记了别名

您可以添加外部查询以检查总值:

SELECT CASE WHEN total > 0 THEN total ELSE 0 END AS total
FROM (
    SELECT 
          sum(contribution.amount) - (SELECT sum(solicitude.amount) 
          FROM solicitude 
          WHERE user_id = 1 AND status_id = 1) as total
       FROM contribution 
       WHERE 
       contribution .user_id = 1
    ) alias;
这个解决方案还可以,但我建议另一种方法。检查此查询的工作方式:

with contribution as (
    select user_id, sum(amount) as amount from contribution
    group by 1),
solicitude as (
    select user_id, sum(amount) as amount from solicitude
    where status_id = 1
    group by 1)
select 
    c.user_id, c.amount as contribution, s.amount as solitude,
    case when c.amount > s.amount then c.amount - s.amount else 0 end as total
from contribution c
join solicitude s on c.user_id = s.user_id;

出于好奇,我在这个设置上做了一个简单的测试:

create table public.solicitude (
    id integer,
    amount numeric,
    create_at timestamp without time zone,
    status_id integer,
    type_id integer,
    user_id integer
);

create table public.contribution (
    id integer,
    amount numeric,
    create_at timestamp without time zone,
    user_id integer
);

insert into contribution (user_id, amount)
select (random()* 50)::int, (random()* 100)::int
from generate_series(1, 4000000);

insert into solicitude (user_id, amount, status_id)
select (random()* 50)::int, (random()* 100)::int, 1
from generate_series(1, 4000000);
结果(毫秒):


我将您的评论解释为
,但该结果不能为负
,因为要求返回0而不是负结果。简单的解决办法是:

否则,我保留了您最初的查询,这很好

对于可能导致无法返回任何行的其他情况,我将替换为两个子选择。但是使用聚合函数可以保证结果行,即使根本找不到给定的
用户id
。比较:


如果减法的结果为
NULL
(因为找不到行或总和为
NULL
),则
magest()
也将返回
0

,但该结果不能为负。请详细说明。你的询问有什么问题?语法可以简化,但做得很好。谢谢您的时间;)我认为这比需要的更昂贵、更冗长。@ErwinBrandstetter-你是说第二个问题吗?@klin:是的,特别是第二个问题,CTE更昂贵,在这里没有必要。但也是第一个:比必要的查询级别多出一个查询级别,并且
grest()
将进一步简化。@ErwinBrandstetter-第二个查询故意冗长。这是一个关于如何连接聚合表的易于理解和修改的示例。此外,有时我觉得有必要写点好东西。这个查询很漂亮,不是吗?关于
,我完全同意。我只是忘了有这样的东西存在;)@ErwinBrandstetter—实际上,我的外部查询解决方案似乎更快。
Erwin's solution with greatest():  922, 905, 922, 904, 904, 904, 905, 912, 905, 922
My solution with an outer query:   796, 795, 814, 814, 815, 795, 815, 796, 815, 796
SELECT GREATEST(sum(amount)
      - (SELECT sum(amount)
         FROM   solicitude 
         WHERE  status_id = 1
         AND    user_id = 1), 0) AS total
FROM   contribution
WHERE  user_id = 1;