mysql: conditional statement problem, greather then - mysql

When I run this query It works
SELECT sum( amount ) AS balance FROM balance WHERE amount >= 100
but when I want to filter for the userid it returns NULL
SELECT sum( amount ) AS balance FROM balance WHERE amount >= 100 AND userid=4

It will return NULL if there are no rows. If you want zero instead then use this:
SELECT IFNULL(SUM(amount), 0) AS balance
FROM balance
WHERE amount >= 100 AND userid = 4
If you believe that the answer should be something other than 0 or NULL then I suggest you run this query to double-check that at least one row is returned and that the data is correct:
SELECT *
FROM balance
WHERE amount >= 100 AND userid = 4

Related

Mysql - most efficient way to retrieve data based on multiple selects and wheres

I'm having trouble finding the most efficient way of retrieving various different sumed values from a Mysql table.
Let's say I've got 4 columns - userid, amount, paid, referral.
I'd like to retrieve the following based on a user id:
1 - the sum of amount that is paid (marked as 1)
2 - the sum of amount that is unpaid (marked as 0)
3 - the sum of amount that is paid and referral (marked as 1 on both paid and referral columns)
4 - the sum of amount that unpaid and referral (marked as 0 on paid and 1 on referral columns)
I've tried an embedded select statement like this:
SELECT (
SELECT sum(payout)
FROM table1
WHERE ispaid = 0 and userid = '100'
) AS unpaid
(
SELECT sum(payout)
FROM table1
WHERE ispaid = 1 and userid = '100'
) AS paid,
(
SELECT sum(payout)
FROM table1
WHERE ispaid = 0 and isreferral = 1 and userid = '100'
) AS refpending,
(
SELECT sum(payout)
FROM table1
WHERE ispaid = 1 and isreferral = 1 and userid = '100'
) AS refpaid
This works, but its slow (or at least feels like it could be quicker) on my server, around 1.5 seconds.
I'm sure there is a better way of doing this with a group statement but can't get my head around it!
Any help is much appreciated.
Thanks
You can use conditional expressions inside SUM():
SELECT
SUM(CASE WHEN ispaid=0 THEN payout END) AS unpaid,
SUM(CASE WHEN ispaid=1 THEN payout END) AS paid,
SUM(CASE WHEN ispaid=0 AND isreferral=1 THEN payout END) AS refpending,
SUM(CASE WHEN ispaid=0 AND isreferral=1 THEN payout END) AS refpaid
FROM table1
WHERE userid = '100'
If a given row is not matched by any CASE...WHEN clause, then the value of the expression is NULL, and SUM() ignores NULLs. You could also have an ELSE 0 clause in there if you want to be more explicit, since SUM() will not be increased by a 0.
Also make sure you have an index on userid in this table to select only the rows you need.

Get result of 2 queries with 1 query

I have 2 following queries in the same table transactions.
transactions table has following 2 columns which is relevant here, registrationId,total and totalPaid.
To get all the paid transactions I run following query
Select SUM(transactions.totalPaid) as netPaid from transactions where deleted is null group by registrationId
To get all the unpaid transactions I run the following query
Select SUM(transactions.total - transactions.totalPaid) as unPaid from transactions where ((totalPaid < total) OR (total < 0)) and deleted is null group by registrationId
How can I combine the query and get both result in one go?
Thank you
You can use case statement to the the unPaid column.
Select sum(transactions.totalPaid) as netPaid
, sum(case when (totalPaid < total) OR (total < 0) then transactions.total - transactions.totalPaid else 0 end) as unPaid
from transactions
where deleted is null
group by registrationId

Percent on basis of row count and row count on basis of condition in single table in mysql

I have four tables with the following structure.
Table 1:
Project - have unique project names (prj_name)
Table 2:
my_records - have the following fields:
record_id,prj_name,my_dept,record_submit_date,record_state
Table 3:
record_states have multiple states where 'Completed' is one.
Table 4:custom_dept_list
dept_name
I need to get the percentage of (records have state as completed) and (Total records) grouped by my_project where my_dept in custom_dept_list and record_submit_date is greater than "some date"
I have tried the following:
Query:
select prj_name,count(record_id) as total,((select count(record_id) from
my_records where record_state='Completed')/(count(record_id)))*100 as
percent from my_records,custom_dept_list where record_state='Completed'
and record_submit_date >= ( CURDATE() - INTERVAL 15 DAY ) and
my_dept=dept_name group by prj_name order by percent desc;
Total records for project A = 50
Total records for project A with record_state='Completed' = 30
Ratio is not coming - (30/50)*100 = 60
It is giving some very big value.
Below is the data from my_records, i have removed record_submit date to make it simple:
|1|prj1|dept1|Completed
|2|prj1|dept1|XYZ
|3|prj1|dept1|Completed
|4|prj1|dept2|XYZ
|5|prj1|dept2|Completed
|6|prj1|dept1|XYZ
|7|prj1|dept1|XYZ
|8|prj1|dept1|XYZ
|9|prj1|dept2|XYZ
|10|prj1|dept2|XYZ
|11|prj1|dept2|Completed
|12|prj1|dept2|Completed
|13|prj1|dept2|Completed
|14|prj1|dept3|XYZ
|15|prj1|dept4|Completed
|16|prj1|dept4|XYZ
|17|prj1|dept5|Completed
|18|prj1|dept6|XYZ
|19|prj1|dept7|XYZ
|20|prj1|dept8|XYZ
|21|prj1|dept10|XYZ
|22|prj1|dept2|XYZ
|23|prj1|dept2|Completed
|24|prj1|dept2|Completed
|25|prj1|dept2|Completed
Data From Custom_dept_List:
dept_name
dept1
dept3
dept4
dept5
dept6
dept8
dept10
I have tried the following queries :
Query 1
select count(record_id) as count,prj_name from my_records,custom_dept_list where my_dept=dept_name group by prj_name order by count desc;
Ouput -- 13
Query 2
select count(record_id) as count,prj_name from my_records,custom_dept_list where my_dept=dept_name and record_state='Completed' group by prj_name order by count desc;
Output -- 4
Query 3
select prj_name,count(record_id) as total,count(case when record_state='Completed' then record_id end) /count(record_id) *100 as percent from my_records join custom_dept_list on my_dept = dept_name where record_state = 'Completed' group by prj_name order by percent desc;
Output :
prj_name total percent
prj1 4 100.0000
First of all, please use proper join instead of multiple tables in your from clause.
Then, you don't need that inner query to get the count with a specific record_state, you can use a case inside the count:
select prj_name,
count(record_id) as total,
count(case when record_state='Completed' then record_id end) /
count(record_id) * 100 as percent
from my_records
join custom_dept_list
on my_dept = dept_name
where record_submit_date >= ( CURDATE() - INTERVAL 15 DAY )
group by prj_name
order by percent desc;
Your problem was probably caused by that inner query, that was not counting each project's completed records, but all the completed records instead.
you do not need this record_state = 'Completed' condition because of this you get only completed record as total recoded. so try without it.
select prj_name,
count(record_id) as total,
count(case when record_state='Completed' then record_id end) /
count(record_id) * 100 as percent
from my_records
join custom_dept_list
on my_dept = dept_name
where record_submit_date >= ( CURDATE() - INTERVAL 15 DAY )
group by prj_name

Count and group by number of records in select query result set

I have a table with emp_id, income, etc.
I wish to get number of records for a query like
select * from table_name where income <= 500;
There will be at least 3 such income groups - which will b given at report generation time.
Further I wish to get all 3 Counts - and group the results by the count of their respective income group - all this in a single query.
What is the easiest way to do this?
Can you try this ,if this doesn't suite your need you may need to write a custom stored procedure
SELECT
sum((income <= 500)) as range1,
sum((income <= 1000)) as range2
FROM table_name
sample fiddle
You can use a CASE expression to create your categories, and then a GROUP BY to summarize the categories.
SELECT COUNT(*) AS num,
CASE WHEN income IS NULL THEN 'missing'
WHEN income <= 0 THEN '0'
WHEN income <= 500 THEN '1 - 500'
WHEN income <= 1000 THEN '501-1000'
ELSE '> 1000'
END AS category
FROM table_name
GROUP BY category WITH ROLLUP
Including the WITH ROLLUP clause will give you an overall count as well as the count of each category.

Mysql select query, splitting column data conditionally into 2 new columns

I have a table called credit_log and the columns are
user_id | amount
The amount can be positive or negative. Positive means credits bought, negative means credits spent.
So, I want to have a query which returns
user_id | Bought | Spent
essentially , i want to sum up positive amount values in to Bought and sum up negative amount in to Spent and I want to group by the user_id
Currently I have a query like this
select user_id,sum(amount) from credit_log group by user_id;
but it sums up both positive and negative values. How can I write a query to separate them?
Some conditional statements inside the query should work nicely:
SELECT
user_id,
SUM(IF(amount > 0, amount, 0)) bought,
SUM(IF(amount < 0, amount, 0)) spent
FROM credit_log
GROUP BY user_id;
select user_id, sum(if(amount>0,amount,0)) bought, sum(if(amount<0,amount,0)) spent
from web_user_credits group by user_id;
I'm not 100% the syntax is the same in mysql... but it looks like it:
select
user_id
,case when amount > 0 then amount else 0 end as bought
,case when amount < 0 then amount else 0 end as spent
from
credit_log
And you can go on to simply place sum() around the case statements (include the end but not as).
check this :
select user_id , sum(if(amount< 0 ,0 ,amount )) as spent,
sum(if(amount> 0 ,0 ,amount )) as bought
from credit_log group by user_id