Sum on same column with two different conditions mysql - 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

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

How to minimize sql query

I have a booking table in MySQL database where I need to get 3 data.
1) Total Booking
2) Pending Booking ( where is_confirm = 1 )
3) Complete Booking ( where is_confirm = 0 )
Now, I am writing 3 separate query to get this but how can I get it using 1 query?
current query:
$booking = new Admin;
$booking->rowQuery("SELECT count(bid) AS totalBooking FROM booking");
$bookingData = $booking->result->fetch_assoc();
$totalBooking = $bookingData['totalBooking'];
$booking->rowQuery("SELECT bid FROM booking WHERE is_confirm = 1 ");
$completeBooking = $booking->rows;
$booking->rowQuery("SELECT bid FROM booking WHERE is_confirm = 0 ");
$pendingBooking = $booking->rows;
you can use case sql . Try this:
SELECT
COUNT(CASE WHEN is_confirm = 1 THEN 1 END) AS confirmCount,
COUNT(CASE WHEN is_confirm = 0 THEN 1 END) AS noconfirmCount,
COUNT(*) AS total
FROM booking;
SELECT count(bid) AS totalBooking FROM booking
UNION
SELECT bid FROM booking
WHERE is_confirm=1
UNION
SELECT bid FROM booking
WHERE is_confirm=0
Aggregate functions usually skip nulls, including group_concat. If you don't mind explodeing the result string later, you could use case expressions to get the total bookings and coma-delimited strings for the IDs:
SELECT COUNT(bid) AS totalBooking,
GROUP_CONCAT(CASE is_confirm WHEN 1 THEN bid END) AS pendingBookings,
GROUP_CONCAT(CASE is_confirm WHEN 0 THEN bid END) AS completeBookings
FROM booking

Grouping by months and by column with diferent values

I am having problems trying to create a query that allow me to group by months and by a column that has different values.
The following is a small representation of the table and columns I need to query.
Table name is requests and has two columns date and status. Status may have the values pending, attended, absent and canceled.
I want to get a query that looks like this
Right now i am trying a subquery on status for each possible value. It works but is a very slow query. It takes arround 48s for 8000 rows.
SELECT
MONTHNAME(date)
(SELECT count(status) FROM requests WHERE status = "pending"),
(SELECT count(status) FROM requests WHERE status = "attended"),
(SELECT count(status) FROM requests WHERE status = "absent"),
(SELECT count(status) FROM requests WHERE status = "canceled")
FROM request
GROUP BY 1;
Any recommendations on how to get the result efficiently? Thank you very much
You could use case whene on status instead of several subselect
select
MONTHNAME(date)
, sum( case when status = "pending" then 1 else 0 end) pending
, sum( case when status = "attended" then 1 else 0 end) attended
, sum( case when status = "absent" then 1 else 0 end) absent
, sum( case when status = "canceled" then 1 else 0 end) canceled
FROM request
GROUP BY MONTHNAME(date) ;

Transform Statement from Access to DB2

I have the following query that I am trying to understand and convert
it to a db2 format:
TRANSFORM Sum(Cases) AS SumOfCases
SELECT Process, Sum(Cases) AS total
FROM tbl
GROUP BY Process
PIVOT tbl.STATUS;
Table has data like:
Process Status Cases
a Cancelled 14
a Closed 179
b Cancelled 20
b Closed 30
b Pending 10
How can I write that query to db2?
I tried the following query:
SELECT Process
, MAX(CASE WHEN STATUS = 'Cancelled' THEN CASES END) "Cancelled"
, MAX(CASE WHEN STATUS = 'Closed' THEN CASES END) "Closed"
, MAX(CASE WHEN STATUS = 'Pending' THEN CASES END) "Pending"
FROM tbl
GROUP BY Process;
Since I do not have MS Access hence I am not confident that if I had done the right thing in db2 or not.
Would appreciate if I could get some advice on this.
Your DB2 query works correctly in replicating Access's crosstab query except you missed the Total column. By the way any aggregate function would work for your CASE/WHEN statements: MIN(), MAX(), MEDIAN(), AVG(), even SUM():
SELECT Process
, SUM(CASES) AS "Total"
, MAX(CASE WHEN STATUS = 'Cancelled' THEN CASES END) AS "Cancelled"
, MAX(CASE WHEN STATUS = 'Closed' THEN CASES END) AS "Closed"
, MAX(CASE WHEN STATUS = 'Pending' THEN CASES END) AS "Pending"
FROM tbl
GROUP BY Process;

Query with multiple SELECT and GROUP BY

I will count of total area's record where there status will different like 'PENDING','SENT INFO','PTP' with group by and multiple select queries but result not got so plese help me.
My query is:
SELECT AREA,
(SELECT COUNT( * ) FROM prospectmaster WHERE ZONE = 'AHMEDABAD' && STATUS = 'PENDING' GROUP BY AREA) AS PENDING,
(SELECT COUNT( * ) FROM prospectmaster WHERE ZONE = 'AHMEDABAD' && STATUS = 'SENT INFO.' GROUP BY AREA) AS CNT
FROM prospectmaster
WHERE ZONE = 'AHMEDABAD' GROUP BY AREA
I want to this type of result.
AREA PENDING INFO SENT PTP
AHMEDABAD 1 2 1
GANDHINAGAR 1 5 4
KHEDA 3 10 9
I think some problem in query but I doesn't got it.So,Please help me.
SELECT AREA,
SUM(CASE WHEN STATUS = 'PENDING' THEN 1 ELSE 0 END) AS PENDING,
SUM(CASE WHEN STATUS = 'SENT INFO.' THEN 1 ELSE 0 END) AS cnt,
SUM(CASE WHEN STATUS = 'PTP' THEN 1 ELSE 0 END) AS PTP
FROM prospectmaster
WHERE ZONE = 'AHMEDABAD'
GROUP BY AREA;
If STATUS has 'SENT INFO.' record in DB with .
SELECT AREA,
SUM(if(STATUS='PENDING',1,0)) AS PENDING,
SUM(if(STATUS='SENT INFO',1,0)) AS "INFO SENT",
SUM(if(STATUS='PTP',1,0)) AS PTP
FROM prospectmaster
WHERE ZONE = 'AHMEDABAD'
GROUP BY AREA;
Because this is mysql, you can simply do this:
SELECT
AREA,
SUM(STATUS = 'PENDING') AS PENDING,
SUM(STATUS = 'SENT INFO.') AS SENT_INFO,
SUM(STATUS = 'PTP') AS PTP
FROM prospectmaster
WHERE ZONE = 'AHMEDABAD'
GROUP BY AREA
This works because in mysql true is 1 and false is 0, so summing a condition counts how many times its true