SQL DB2 Toad - Sum from two tables by ID - sql

I was hoping to find the sum from two tables with columns ID and Amount, grouping by ID.
My first attempt was to UNION the two tables first and then conduct a sum and group by, but I was hoping to know of a better way.
Inputs:
Table 1
ID Amount
123 100
123 100
145 500
167 600
Table 2
ID Amount
123 100
123 100
145 500
199 600
Output
ID Amount
123 400
145 1000
167 600
199 600

You can do:
select id, sum(amount) as amount
from (
select id, amount from table_1
union all
select id, amount from table_2
) x
group by id

Related

SQL - Summing/counting rows based on matching columns

I have the 2 following tables
Tracking
tracking_id item_extension quantity
a 144 100
b 144 200
c 250 150
Account
tracking_id account
a 999
b 999
c 999
Here's my query -
SELECT sum(qty) as qty, count(item_extension) as total, t.tracking_id, item_extension, account
FROM Tracking t
INNER JOIN Account a ON t.tracking_id = a.tracking_id
GROUP BY t.tracking_id, item_extension, account
What I want to happen here is get count of item_extension and sum of quantity based on matching account/item_extension fields. So because there are 2 rows with matching account and item_extension fields, it should sum up 2 of them like so:
qty total tracking_id item_extension account
300 2 a 144 999
300 2 b 144 999
150 1 c 250 999
Instead I get this result:
qty total tracking_id item_extension account
100 1 a 144 999
200 1 b 144 999
150 1 c 250 999
Is there a good way of doing this?
You want to count item_extension values that are not in the current row. So, use window functions. I think this does what you want:
SELECT sum(qty) as qty,
sum(count(*)) over (partition by item_extension) as total,
t.tracking_id, item_extension, account
FROM Tracking t
INNER JOIN Account a ON t.tracking_id = a.tracking_id
GROUP BY t.tracking_id, item_extension, account;

Dividing a sum value into multiple rows due to field length constraint

I am migrating financial data from a very large table (100 million+ of rows) by summarizing the amount and insert them into summary table. I ran into problem when the summary amount (3 billions) is larger than what the field in the summary table can hold (can only hold up to 999 millions.) Changing the field size is not an option as it requires a change process.
The only option I have is to divide the amount (the one that breach the size limit) into smaller ones so it can be inserted into the table.
I came across this SQL - I need to divide a total value into multiple rows in another table which is similar except the number of rows I need to insert is dynamic.
For simplicity, this is how the source table might look like
account_table
acct_num | amt
-------------------------------
101 125.00
101 550.00
101 650.00
101 375.00
101 475.00
102 15.00
103 325.00
103 875.00
104 200.00
104 275.00
The summary records are as follows
select acct_num, sum(amt)
from account_table
group by acct_num
Account Summary
acct_num | amt
-------------------------------
101 2175.00
102 15.00
103 1200.00
104 475.00
Assuming the maximum value in the destination table is 1000.00, the expected output will be
summary_table
acct_num | amt
-------------------------------
101 1000.00
101 1000.00
101 175.00
102 15.00
103 1000.00
103 200.00
104 475.00
How do I create a query to get the expected result? Thanks in advance.
You need a numbers table. If you have a handful of values, you can define it manually. Otherwise, you might have one on hand or use a similar logic:
with n as (
select (rownum - 1) as n
from account_table
where rownum <= 10
),
a as (
select acct_num, sum(amt) as amt
from account_table
group by acct_num
)
select acct_num,
(case when (n.n + 1) * 1000 < amt then 1000
else amt - n.n * 1000
end) as amt
from a join
n
on n.n * 1000 < amt ;
A variation along these lines might give some ideas (using the 1,000 of your sample data):
WITH summary AS (
SELECT acct_num
,TRUNC(SUM(amt) / 1000) AS times
,MOD(SUM(amt), 1000) AS remainder
FROM account_table
GROUP BY acct_num
), x(acct_num, times, remainder) AS (
SELECT acct_num, times, remainder
FROM summary
UNION ALL
SELECT s.acct_num, x.times - 1, s.remainder
FROM summary s
,x
WHERE s.acct_num = x.acct_num
AND x.times > 0
)
SELECT acct_num
,CASE WHEN times = 0 THEN remainder ELSE 1000 END AS amt
FROM x
ORDER BY acct_num, amt DESC
The idea is to first build a summary table with div and modulo:
ACCT_NUM TIMES REMAINDER
101 2 175
102 0 15
103 1 200
104 0 475
Then perform a hierarchical query on the summary table based on the number of "times" (i.e. rows) you want, with an extra for the remainder.
ACCT_NUM AMT
101 1000
101 1000
101 175
102 15
103 1000
103 200
104 475

MS-Access : How to sum multiple values from different tables according to dates

I have two similar tables as follows
Table 1
Date Amount Tax
4/1/2016 1000 100
4/1/2016 2000 200
5/3/2016 1500 150
5/6/2016 1000 100
5/6/2016 3000 300
7/9/2016 2500 250
Table 2
Date Amount Tax
4/1/2016 1000 100
4/2/2016 3000 300
5/3/2016 1500 150
5/9/2016 4000 400
8/11/2016 3000 300
10/9/2016 2000 200
dates can be similar or different in both tables.
I want two queries.
First, a query which gives me sum of amount and tax from each date from both tables between required dates. Eg: Table 1 have 2 entries and table 2 have 1 entry for 4/1/2016. so the result should be as below (summing up all three entries)
Date Amount Tax
4/1/2016 4000 400
4/2/2016 3000 300
5/3/2016 3000 300
5/6/2016 4000 400
5/9/2016 4000 400
7/9/2016 2500 250
8/11/2016 3000 300
10/9/2016 2000 200
Second,a query which gives of sum of amount and tax for each month from both tables between required dates. Eg output as below
Date Amount Tax
4/2016 4000 400
5/2016 11000 1100
7/2016 2500 250
8/2016 3000 300
10/2016 2000 200
Query that have I have written till now( not working )
SELECT date, sum(Amount),sum(Tax)
From Table1
WHERE Date BETWEEN #04/01/2016# AND #12/31/2016#
UNION ALL
SELECT date, sum(Amount),sum(Tax)
From Table2
WHERE Date BETWEEN #04/01/2016# AND #12/31/2016#
GROUP BY Date
For first query, consider a union query derived table with outer query aggregation:
SELECT q1.[Date], SUM(q1.Amount) AS DayTotalAmt, SUM(q1.Tax) AS DayTotalTax
FROM
(SELECT [Date], Amount, Tax
FROM Table1
UNION ALL
SELECT [Date], Amount, Tax
FROM Table2
) AS q1
GROUP BY q1.[Date]
For second query, consider using first query as a source with another outer query layer that runs a WHERE filter with month/year aggregation:
SELECT Format(q2.Date, "M/YYYY"), SUM(q2.DayTotalAmt) AS MonthTotalAmt,
SUM(q2.DayTotalTax) AS MonthTotalTax
FROM
(SELECT q1.[Date], SUM(q1.Amount) AS DayTotalAmt, SUM(q1.Tax) AS DayTotalTax
FROM
(SELECT [Date], Amount, Tax
FROM Table1
UNION ALL
SELECT [Date], Amount, Tax
FROM Table2) AS q1
GROUP BY q1.[Date]
) AS q2
WHERE q2.Date BETWEEN CDate("4/1/2016") AND CDate("12/31/2016")
GROUP BY Format(q2.Date, "M/YYYY")
Or if you save first query:
SELECT Format(q.Date, "M/YYYY"), SUM(q.DayTotalAmt) AS MonthTotalAmt,
SUM(q.DayTotalTax) AS MonthTotalTax
FROM Query1 q
WHERE q.Date BETWEEN CDate("4/1/2016") AND CDate("12/31/2016")
GROUP BY Format(q.Date, "M/YYYY")

New column with rowtotals

I'm having some trouble to achieve the folowing result.
This is my current table:
ID NR COST
1 7001 100
2 7001 50
3 7020 800
4 7020 190
5 7050 205
6 7050 80
And this is the table I want to achieve:
ID NR COST TOTAL
1 7001 100 150
2 7001 50 150
3 7020 800 990
4 7020 190 990
5 7050 205 285
6 7050 80 285
So I want to create an extra column, where the sum of the same 'NR' column is.
I have tried working with SUM, but then the whole sum of the cost column is taken.
This is my current query:
SELECT distinct id, nr, cost, sum(cost) as total
FROM customers
group by id, nr, cost
You can use a subquery to calculate the total for each NR and then just add it to the original result:
SELECT id,
nr,
cost,
A.subtotal AS TOTAL
FROM table1
INNER JOIN (SELECT nr,
Sum(cost) AS subTotal
FROM table1
GROUP BY nr) AS A
ON table1.nr = A.nr
You can self join with an aggregate query:
SELECT id, mytalbe.nr, cost, total
FORM mytable
JOIN ON (SELECT nr, SUM(cost) AS total
FROM mytable
GROUP BY nr) t ON t.nr = mytable.nr

oracle sql query to get data from two tables of similar type

I have two tables ACTUAL AND ESTIMATE having unique column(sal_id, gal_id, amount, tax).
In ACTUAL table I have
actual_id, sal_id, gal_id, process_flag, amount, tax
1 111 222 N 100 1
2 110 223 N 200 2
In ESTIMATE table I have
estimate_id, sal_id, gal_id, process_flag, amount, tax
3 111 222 N 50 1
4 123 250 N 150 2
5 212 312 Y 10 1
Now I want a final table, which should have record from ACTUAL table and if no record exist for sal_id+gal_id mapping in ACTUAL but exist in ESTIMATE, then populate estimate record (along with addition of amount and tax).
In FINAL table
id sal_id, gal_id, actual_id, estimate_id, total
1 111 222 1 null 101 (since record exist in actual table for 111 222)
2 110 223 2 null 202 (since record exist in actual table for 110 223)
3 123 250 null 4 51 (since record not exist in actual table but estimate exist for 123 250)
(for 212 312 combination in estimate, since record already processed, no need to process again).
I am using Oracle 11g. Please help me on writing a logic in a single sql query?
Thanks.
There are several ways to write this query. One way is to use join and coalesce:
select coalesce(a.sal_id, e.sal_id) as sal_id,
coalesce(a.gal_id, e.gal_id) as gal_id,
coalesce(a.actual_value, e.estimate_value) as actual_value
from actual a full outer join
estimate e
on a.sal_id = e.sal_id and
a.gal_id = e.gal_id
This assumes that sal_id/gal_id provides a unique match between the tables.
Since you are using Oracle, here is perhaps a clearer way of doing it:
select sal_id, gal_id, actual_value
from (select *,
max(isactual) over (partition by sal_id, gal_id) as hasactual
from ((select 1 as isactual, *
from actual
) union all
(select 0 as isactual, *
from estimate
)
) t
) t
where isactual = 1 or hasactual = 0
This query uses a window function to determine whether there is an actual record with the matching sal_id/gal_id. The logic is to take all actuals and then all records that have no match in the actuals.