СОЕДИНИТЕ две таблицы и получите результаты - PullRequest
3 голосов
/ 10 января 2020

У меня есть две таблицы, как показано ниже:

tbl_main
----------------------------------
id | bucket | amount 
1  |  1     | 10
2  |  2     | 10
3  |  1     | 20
4  |  4     | 10
5  |  5     | 20
6  |  6     | 30
7  |  6+    | 50
8  |  3     | 30
9  |  5     | 50

И еще одна таблица, как показано ниже

tbl_sub
----------------------------------
id | bucket | amount | status
1  |  1     | 10     |  1
2  |  1     | 10     |  1
3  |  1     | 20     |  1
4  |  4     | 10     |  2
5  |  5     | 20     |  1

Я хочу объединить эти две таблицы, используя сегменты, и получить общую сумму каждого сегмента в две таблицы, где таблица tbl_sub столбец status равен 1

Ожидаемый результат

bucket | main_amount | sub_amount
-----------------------------------
 1     |      30     |     40       
 2     |      10     |      0       
 3     |      30     |      0      
 4     |      10     |      0      
 5     |      70     |     20      
 6     |      30     |      0     
 6+    |      50     |      0      

Я не получаю его. Где я иду не так, вот мой запрос

SELECT cl.bucket
     , SUM(cl.amount) as main_total
FROM `tbl_main` cl
    JOIN(SELECT bucket, SUM(amount)
         FROM `tbl_sub`
         WHERE status = '1'
         GROUP BY bucket) fl on cl.bucket = fl.bucket
 GROUP BY cl.bucket

Вот схема и Db Fiddle ссылка того же

CREATE TABLE `tbl_main` ( `id` INT ,  `bucket` VARCHAR(5) ,  `amount` INT ,    PRIMARY KEY  (`id`));     

CREATE TABLE `tbl_sub` ( `id` INT  ,  `bucket` VARCHAR(5) ,  `amount` INT ,  `status` INT,    PRIMARY KEY  (`id`));


INSERT INTO `tbl_main` (`id`, `bucket`, `amount`) VALUES ('1', '1', '10'), ('2', '2', '10'), ('3','1', '20'), ('4', '4', '10'), ( '5','5', '20'), ( '6','6', '30'), ( '7','6+', '50'), ('8','3', '30'), ('9', '5', '50');


INSERT INTO `tbl_sub` (`id`, `bucket`, `amount`, `status`) VALUES ( '1','1', '10', '1'), ('2','1', '10', '1'), ('3','1', '20', '1'), ('4','4', '10', '2'), ('5','5', '20', '1');

Ответы [ 4 ]

2 голосов
/ 10 января 2020

Попробуйте это:

Используйте основной запрос для получения main_amount и используйте подзапрос для вычисления sub_amount, связанного с основным сегментом, следующим образом:

SELECT cl.bucket,SUM(cl.amount) as main_total,
COALESCE((SELECT SUM(s.amount) FROM `tbl_sub` s WHERE s.status='1' AND s.bucket = 
cl.bucket), 0)
FROM `tbl_main` cl
GROUP BY cl.bucket

SQL Скрипка

1 голос
/ 10 января 2020

2 ошибки в вашем запросе:

  1. вы не используете рассчитанную сумму из подзапроса

  2. вы используете соединение который будет возвращать только совпадающие записи - используйте левое соединение, чтобы получить все из tbl_main и coalesce, чтобы установить нулевые значения в ноль

drop table if exists t,t1;
create table t
(id int, bucket int, amount int);
insert into t values
(1  ,  1     , 10),
(2  ,  2     , 10),
(3  ,  1     , 20),
(4  ,  4     , 10),
(5  ,  5     , 20),
(6  ,  6     , 30),
(7  ,  6     , 50),
(8  ,  3     , 30),
(9  ,  5     , 50);
create table t1(id int, bucket int, amount int, status int);
insert into t1 values
(1  ,  1     , 10     ,  1),
(2  ,  1     , 10     ,  1),
(3  ,  1     , 20     ,  1),
(4  ,  4     , 10     ,  2),
(5  ,  5     , 20     ,  1);

SELECT cl.bucket
     , SUM(cl.amount) as main_total
     , coalesce(max(subamt),0) subamt
FROM t cl
left JOIN(SELECT bucket, SUM(amount) subamt
         FROM t1
         WHERE status = '1'
         GROUP BY bucket) fl on cl.bucket = fl.bucket
 GROUP BY cl.bucket;

+--------+------------+--------+
| bucket | main_total | subamt |
+--------+------------+--------+
|      1 |         30 |     40 |
|      2 |         10 |      0 |
|      3 |         30 |      0 |
|      4 |         10 |      0 |
|      5 |         70 |     20 |
|      6 |         80 |      0 |
+--------+------------+--------+
6 rows in set (0.00 sec)

это можно написать менее подробно, используя условное агрегирование

SELECT t.bucket
     , SUM(t.amount) as main_total
     , sum(case when t1.amount is not null and t1.status = 1 then t1.amount else 0 end )subamt
FROM t 
left join t1 on  t1.bucket = t.bucket
group by t.bucket;
1 голос
/ 10 января 2020

SQL DEMO

Вам необходимо 2 отдельных запроса

SELECT t.bucket
     , t.main_total
     , COALESCE(p.sub_total, 0) as sub_total
FROM ( SELECT bucket, SUM(amount) as main_total
       FROM `tbl_main`
       GROUP BY bucket) as t
LEFT JOIN ( SELECT bucket, SUM(amount) as sub_total
       FROM `tbl_sub`
       WHERE status='1'
       GROUP BY bucket) as p
 ON t.bucket = p.bucket
ORDER BY t.bucket
0 голосов
/ 10 января 2020

Можно также использовать with as:

with sub_tab as (SELECT bucket, SUM(amount) as sub_total
       FROM `tbl_sub`
       WHERE status='1'
       GROUP BY bucket)

SELECT t.bucket
     , SUM(t.amount) as main_total 
     , COALESCE(sub_tab.sub_total, 0) as sub_total
     from `tbl_main` t join sub_tab on 
 ON t.bucket = sub_tab.bucket
ORDER BY t.bucket
...