Query to get column totals and Subtract MySQL - mysql

I have a transaction table
I am able to get all the debit and credit transaction totals by property separately using these queries
SELECT property, SUM(amount) as creditamount FROM transactions WHERE transactions.type="CREDIT" GROUP BY property
SELECT property, SUM(amount) as debitamount FROM transactions WHERE transactions.type="DEBIT" GROUP BY property
I am facing difficulty in having these two queries done in a single query so that i can subtract credit amount and debit amount for each row and list it according to the property
I tried using sub queries but multiple rows are returned.
Any way to achieve this?

Conditional aggregation may be what you are looking for.
SELECT property,
SUM(case when type = 'Credit' then amount else 0 end) as creditamount,
SUM(case when type = 'Debit' then amount else 0 end) as debitamount,
SUM(case when type = 'Credit' then amount else 0 end) -
SUM(case when type = 'Debit' then amount else 0 end) as diff
FROM transactions
GROUP BY property

Use self join
select debitamount , creditamount
from (select sum(amount) income
from transactions
WHERE transactions.type="CREDIT"
GROUP BY property) i
JOIN (select sum(rate) debitamount
from transactions
WHERE transactions.type="DEBIT"
GROUP BY property) e
Refer this question

Related

How to create a calculated row in sql or power bi?

I am trying to do a calculation on 2 rows on a SQL I wrote so I can have a 3 row that will be Profit and show the amount is it possible?
This dummy data not true to any company!
see below :
SELECT a.pcg_type GL_Acoount_Group,
Abs(sum(b.debit-b.credit)) GL_Amount
FROM dolibarr.llx_accounting_account a
JOIN dolibarr.llx_accounting_bookkeeping b
ON a.account_number = b.numero_compte
WHERE a.pcg_type IN ('INCOME', 'EXPENSE')
ANDa.fk_pcg_version = 'PCG99-BASE'
GROUP BY a.pcg_type
Results:
Group. Amt
INCOME 379200
EXPENSE 65700
Expected Results:
Group. Amt
INCOME 379200
EXPENSE 65700
PROFIT 313500
Use ROLLUP for adding an extra row and use CASE statement inside SUM() function for treating expense value as negative for calculation
--MySQL
SELECT COALESCE(acc_type, 'Profit') "Group"
, ABS(SUM(CASE WHEN acc_type = 'EXPENSE' THEN -amount ELSE amount END)) amt
FROM test
GROUP BY acc_type WITH ROLLUP
Another way by using UNION ALL
SELECT acc_type "Group"
, SUM(amount) Amt
FROM test
GROUP BY acc_type
UNION ALL
SELECT 'Profit' AS "Group"
, SUM(CASE WHEN acc_type = 'EXPENSE' THEN -amount ELSE amount END) Amt
FROM test
Please check this url https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=f859036ffcb3d808330bce5346daee1e

Sum on same column with two different conditions mysql

I have a table named Order with schema as
user_id, state amount
11 success 100
11 FAILED 10
11 FAILED 10
11 success 17
state can have two values (Success/Failed).
I want to fetch sum(amount) when state = "SUCCESS" - sum(amount) when state = "FAILED"
means difference total amount when success - total amount when failed.
I can solve this problem in 2 queries.
A = select id, sum(amount) when state = "SUCCESS"
B = select id, sum(amount) when state = "FAILED"
And solution will be A-B.
Is there any way I can achieve this in single sql query?
use case when
select user_id,sum(case when state = 'SUCCESS' then amount else 0 end)-sum(case when state = 'FAILED' then amount else 0 end)
from table group by user_id
Use conditional aggregation:
select id,
sum(case when state = 'SUCCESS' then amount else - amount end) as total
from t
where state in ('SUCCESS', 'FAILED')
group by id;
I assume that you want this sum per id and not overall in the table.
select sum(case when state = "SUCCESS" then amount else o end) -
sum(case when state = "FAILED" then amount else o end)
from tbl
group by userid

Combining two resulted columns on order by when one is null

I have a inventory table where i have records which refers to inventory movement of products sold by a company. The movement have 'INCOMING', 'OUTGOING' params based on type of inventory movement. It also has one more column which says the type of 'INCOMING' or 'OUTGOING'... like incoming because of NEW STOCK arrival, outgoing because of PURCHASE by customer... etc...
Now am making a report where i want to list non sold products for a long while. So am making the following query...
SELECT p.id as pid, product_name, DATEDIFF(NOW(), MAX(case when movement_type='OUTGOING' and movement_type_category='PURCHASED' then movement_on end)) AS unsold_days_since_last_sale, DATEDIFF(NOW(), MIN(case when movement_type='INCOMING' and movement_type_category='NEW_STOCK' and quantity>0 then movement_on end)) AS unsold_days_since_first_inventory_in, MAX(case when movement_type='INCOMING' and movement_type_category='NEW_STOCK' and quantity>0 then movement_on end) AS last_inv_in from inventory_movement im left join products p on im.product = p.id GROUP BY product having last_inv_in > 0 ORDER BY unsold_days_since_last_sale desc limit 100
And i get the following output as shown in the image.
This output is nearly correct but with one issue. If a product was never sold even once in the past the column where i try to get days different between CURRENT DAY and LAST SOLD DAY will return null. In that case i need the DAYS difference between CURRENT DAY and FIRST INVENTORY IN of that product to be on the place so i can order that column descending and get the output. But i can get those data as only 2 different columns not as one column. Can someone help me to write a query to get it as combined column so i can sort that data to get result. Am attaching my inventory movement table snap also to show how the data look like...
I think IfNull function will resolve your issue.
Here's modified query.
SELECT p.id AS pid,
product_name,
Datediff(Now(), Ifnull(Max(CASE
WHEN movement_type = 'OUTGOING'
AND movement_type_category =
'PURCHASED' THEN
movement_on
end), Min(CASE
WHEN movement_type = 'INCOMING'
AND movement_type_category =
'NEW_STOCK'
AND quantity > 0 THEN
movement_on
end))) AS
unsold_days_since_last_sale,
Datediff(Now(), Min(CASE
WHEN movement_type = 'INCOMING'
AND movement_type_category = 'NEW_STOCK'
AND quantity > 0 THEN movement_on
end)) AS
unsold_days_since_first_inventory_in,
Max(CASE
WHEN movement_type = 'INCOMING'
AND movement_type_category = 'NEW_STOCK'
AND quantity > 0 THEN movement_on
end) AS last_inv_in
FROM inventory_movement im
LEFT JOIN products p
ON im.product = p.id
GROUP BY product
HAVING last_inv_in > 0
ORDER BY unsold_days_since_last_sale DESC
LIMIT 100

Get Available Balance from transaction table using MYSQL

I tried to get available balance of specific account number using SQL QUERY my code is below:
select sum(amount) as Cr form transaction where credit=1 and account_no=2549
Union
select sum(amount) as Dr form transaction where debit=1 and account_no=2549
Difference Cr-Dr
You could use case to get sum for credit and debit in single query as
select sum(case when credit=1 then amount else 0 end) as Cr ,
sum(case when debit=1 then amount else 0 end) Dr,
sum(case when credit=1 then amount else 0 end) - sum(case when debit=1 then amount else 0 end) as available_balance
from `transaction`
where account_no=2549
The below query should work for you to get available balance.
select sum(amt) from
(select
case
when credit=1 then amount
when debit=1 then -amount
else 0
end as amt
from transaction
where account_no = 5294)t;

sql group by date gives same value everyday

So I want to group by days for statistics so I have data on each day (type 1 is bought and 0 is sold) but the query gives me the same result everyday and that is not correct can someone help me with this code?
SELECT
DATE(from_unixtime(credit_transaction_time)) AS data_date,
total_spend AS credits_spend,
total_bought AS credits_bought
FROM credit_transactions
JOIN (SELECT SUM(`credit_transaction_amount`) AS total_spend FROM credit_transactions WHERE `credit_transaction_type` = 0 GROUP BY DATE(from_unixtime(credit_transaction_time))) AS spend
JOIN (SELECT SUM(`credit_transaction_amount`) AS total_bought FROM credit_transactions WHERE `credit_transaction_type` = 1 GROUP BY DATE(from_unixtime(credit_transaction_time))) AS bought
GROUP BY DATE(from_unixtime(credit_transaction_time))
Use conditional aggregation:
SELECT DATE(from_unixtime(credit_transaction_time)) AS data_date,
SUM(CASE WHEN credit_transaction_type = 0 THEN credit_transaction_amount ELSE 0 END) as credits_spend,
SUM(CASE WHEN credit_transaction_type = 1 THEN credit_transaction_amount ELSE 0 END) as credits_bought
FROM credit_transactions
GROUP BY DATE(from_unixtime(credit_transaction_time));
Your query doesn't work because you don't have an ON condition. In most databases, this would result in a syntax error, but MySQL allows this syntax.