Mysql group by and sum two different columns - mysql

I have this table called transactions, where agents can give certain amounts to other agents, we have 2 columns, one called agent_from which is the agent that put the amount and agent_to is the one reciving the amount.
An example with the id 1 would be that the agent2 is giving an amount of 300 to the agent8
The report that I would like to do is a sum and a group by agent_from and agent_to
Right now I am able to make the query separatly like this
SELECT agent_from,
SUM(amount) as from_transaccions
FROM `transactions` GROUP BY agent_from;
This would give me this result:
This return a sum of all the amounts made by agent_from.
Now I can repeat this query changing the column name from agent_from to agent_to so I can get the sum of all the amounts recived by agent_to, that will look like this:
An example would be that the agent8 recived 2 transaccions (300 + 450) = 750
Now what I want to do is make this 2 querys into one that will look like this:

Refer query below -
with data_cte as (
(select agent_from agent, amount, 'af' flag from transactions) union all
(select agent_to agent, amount, 'at' flag from transactions)
)
select agent,
sum(case when flag='af' then amount else 0 end) from_sum,
sum(case when flag='at' then amount else 0 end) to_sum
from data_cte
group by agent
union all
select 'total' as col1,
sum(case when flag='af' then amount else 0 end) from_sum,
sum(case when flag='at' then amount else 0 end) to_sum
from data_cte
group by col1
order by agent
fiddle.

Use UNION ALL to split each row of the table to 2 rows so that you separate the 2 agents and aggregate:
SELECT COALESCE(agent, 'total') agent,
SUM(`from`) `from`,
SUM(`to`) `to`
FROM (
SELECT agent_from agent, amount `from`, 0 `to` FROM `transactions`
UNION ALL
SELECT agent_to, 0 `from`, amount `to` FROM `transactions`
) t
GROUP BY agent WITH ROLLUP
ORDER BY GROUPING(agent);
See the demo.

Related

Summing of count result at same level

I'm trying to sum the results of count(id) at the same level, in order to find out the relative portion of the count(id) from the overall count.
The count is grouped by the respective previous number, and I want to stay at the same table and have it all together.
`
select totalattempts, count(totalattempts) allattempts, count(case when success>0 then totalattempts else null end) successfulattempts
from (
select *, case when success> 0 then attemptspresuccess+1 else attemptspresuccess end totalattempts
from (select orderid, count(orderid) attemptspresuccess, count(case when recoveredPaymentId is not null then recoveredPaymentId end ) success from (
select orderid, recoveredPaymentId
from errors
where platform = 'woo'
) alitable
group by orderid) minitable ) finaltable
group by totalattempts
order by totalattempts asc
`
I need to add another column that basically would have, to put it simply, count(totalattempts)/sum(count(totalattempts).
I'm running out of ideas basically.
I can't use windows as this is an app of retool which doesn't support that
Assuming some test data here:
DECLARE #table TABLE (AttemptNumber INT IDENTITY, Success BIT)
INSERT INTO #table (Success) VALUES
(0),(0),(0),(0),(1),(1),(0),(0),(0),(0),(0),(1),(0),(1),(0),(0),
(0),(0),(1),(0),(0),(0),(0),(1),(0),(1),(0),(0),(0),(1),(0),(0)
I sounds like you want to know how many attempts there were, how many were successful and what that is a percentage?
SELECT COUNT(Success) AS TotalCount,
COUNT(CASE WHEN Success = 1 THEN 1 END) AS SuccessCount,
COUNT(CASE WHEN Success = 1.0 THEN 1 END)/(COUNT(Success)+.0) AS SuccessPct
FROM #table
TotalCount SuccessCount SuccessPct
--------------------------------------
32 8 0.2500000000000

SQL query for cumulative sum or subtract

how to create columns from unique values of a column and do a cumulative addition or subtraction.
I have a record of transactions like this
transaction_id
created_at
transaction_type
amount
124
2020-08-06 17:00:09
2
25.00
123
2020-08-06 17:00:03
1
50.00
There are various types of transactions, which in turn have different effects .Some results are withdrawals from th account, some are deposits and others don’t affect it at all. This information is summarized in another table (let’s call it ‘transaction_types’), as shown below:
id
description
effect
1
Manual Deposit
add
2
Direct Payment
subtract
id in the table transaction_type is a foreign key transactions. transaction_type = transactions_type.id
now if the initial amount is $10000 I need to create a table like this
transaction_id
initial_balance
deposit
withdrawal
final_balance
123
100000
50
100050
124
100050
25
100025
I don't know how to create new columns based on unique values in some columns also to start a cumulative sum from 10000. This is the query I tried select f.transaction_id, t.created_at, sum(case when d.effect = 'subtract' then -1 else 1 end * amount) from f inner join d on f.transaction_type = d.id
WITH RECURSIVE RowNums AS
(
SELECT
transaction_id,
created_at,
CAST(amount AS SIGNED) AS amount,
effect,
ROW_NUMBER() OVER
(
ORDER BY
created_at,
transaction_id
) AS RowNum
FROM transactions t
JOIN transaction_types tt
ON t.transaction_type = tt.id
),
Balances AS
(
SELECT
transaction_id,
created_at,
amount,
effect,
100000 AS initial_balance,
100000 +
(
CASE effect
WHEN 'add' THEN amount
WHEN 'subtract' THEN (-(amount))
END
) AS final_balance,
RowNum
FROM RowNums
WHERE RowNum = 1
UNION ALL
SELECT
rn.transaction_id,
rn.created_at,
rn.amount,
rn.effect,
b.final_balance,
b.final_balance +
(
CASE rn.effect
WHEN 'add' THEN rn.amount
WHEN 'subtract' THEN (-(rn.amount))
END
),
rn.RowNum
FROM Balances b
JOIN RowNums rn
ON (b.RowNum + 1) = rn.RowNum
)
SELECT
transaction_id,
initial_balance,
CASE effect
WHEN 'add'
THEN CAST(amount AS CHAR(20))
ELSE ''
END AS deposit,
CASE effect
WHEN 'subtract'
THEN CAST(amount AS CHAR(20))
ELSE ''
END AS withdrawal,
final_balance
FROM Balances
ORDER BY
created_at,
transaction_id
source : https://www.reddit.com/r/sqltutorial/comments/sx3ycb/comment/hxr6f9l/?utm_source=share&utm_medium=web2x&context=3

SQL query to get percentages within a grouping

I've looked over similar questions and I just can't seem to get this right.
I have a table with three columns: ID, Date, and Method. None are unique.
I want to be able to see for any given date, how many rows match a certain pattern on Method.
So, for example, if the table has 100 rows, and 8 of them have the date "01-01-2020" and of those 8, two of them have a method of "A", I would want a return row that says "01-01-2020", "8", "2", and "25%".
My SQL is pretty rudimentary. I have been able to make a query to get me the count of each method by date:
select Date, count(*) from mytable WHERE Method="A" group by Date;
But I haven't been able to figure out how to put together the results that I am needing. Can someone help me out?
You could perform a count over a case expression for that method, and then divide the two counts:
SELECT date,
COUNT(*),
COUNT(CASE method WHEN 'A' THEN 1 END),
COUNT(CASE method WHEN 'A' THEN 1 END) / COUNT(*) * 100
FROM mytable
GROUP BY date
I'm assuming you're interested in all methods rather than just 'A', so you could do the following:
with ptotals as
(
SELECT
thedate,
count(*) as NumRows
FROM
mytable
group by
thedate
)
select
mytable.thedate,
mytable.themethod,
count(*) as method_count,
100 * count(*) / max(ptotals.NumRows) as Pct
from
mytable
inner join
ptotals
on
mytable.thedate = ptotals.thedate
group by
mytable.thedate,
mytable.themethod
You can use AVG() for the ratio/percentage:
SELECT date, COUNT(*),
SUM(CASE WHEN method = 'A' THEN 1 ELSE 0 END),
AVG(CASE WHEN method = 'A' THEN 100.0 ELSE 0 END)
FROM t
GROUP BY date;

req_type wise count id in one query

I have an sql query problem . I don't want to execute three times query for same result.
In my table I have one field req_type which have three parameter ,
either 1, either 2, either 3 .
I want counter based on req_type in one query instead of by executing query 3 times like below
select count(id) as premium FROM tablename where req_type=1
select count(id) as premium1 FROm tablename where req_type=2
select count(id) as premium2 FROm tablename where req_type=3
I am stuck , can anybody help me?
You could use case for such type of count
select sum(case when req_type=1 then 1 else 0 end) as premium,
sum(case when req_type=2 then 1 else 0 end) as premium1,
sum(case when req_type=3 then 1 else 0 end) as premium2
FROM tablename
Use one query instead of threes by using group by cluase
select req_type , count(id) as premium
FROM tablename
where req_type in (1,2,3)
group by req_type
Use a GROUP BY
SELECT req_type, COUNT(id) AS count_premium
FROM tablename
GROUP BY req_type;

Showing taxes per invoice items from database

I have problem with getting tax values from database. I will simplify it as possible i can.
First table is
Invoices
(
`Id`,
`Date`,
`InvoiceNumber`,
`Total`
)
Second table is
`InvoiceItems`
(
`Id`,
`Total`,
`TotalWithoutTax`,
`TotalTax`,
`InvoiceId`
)
InvoiceId is a foreign key for Id column from previous table Invoices
Third table is
`InvoiceItemTaxes`
(
`Id`,
`TaxAmmount`,
`InvoiceItemId`,
`TaxId`
)
and fourth table
`Taxes`
(
`Id`,
`Value`
)
This last table contains three taxes, let's say 3, 10 and 15 percent.
I am trying to get something like this - table with columns InvoiceNumber, Total without taxes, Tax1, Tax2, Tax3 and Total with taxes.
I tried a lot of different approaches and i simply cannot get tax amount for every invoice. End result would be table where i can see every invoice with specified amounts of every tax (sum of each tax amount for every invoice item).
If I'm understanding correctly, you can use conditional aggregation with sum and case to get the breakdown by tax group:
select i.id, i.invoicenumber, i.total as pretaxtotal,
sum(case when t.value = 3 then iit.TaxAmmount end) taxes_3,
sum(case when t.value = 10 then iit.TaxAmmount end) taxes_10,
sum(case when t.value = 15 then iit.TaxAmmount end) taxes_15,
sum(ii.Total) as overalltotal
from invoices i
join InvoiceItems ii on i.id = ii.invoiceid
join InvoiceItemTaxes iit on ii.id = iit.InvoiceItemId
join Taxes t on t.id = iit.taxid
group by i.id, i.invoicenumber, i.total
Some of the fields may be a little off -- the sample data was not complete.