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
Related
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.
I am working on a game with a MySql database. In the game we have a system where characters have a debt that can be paid. We track each debt singularly and flag whether its paid or not with a Boolean 0,1.
I am trying to understand how in a single query I can sum the total paid amount as well as the total owed amount from a single character ID. The tables are
charid, amount, paid (the boolean)
Currently if I just want to find out how much they owe I simply place
SELECT sum(amount) FROM debts WHERE paid='0';
So how would I modify this to create a resulting column for both paid='0' and paid='1' ?
Thanks all.
Use conditional aggregation. Since the paid flag holds 0/1 values, you can just do:
select
sum(paid * amount) amount_paid,
sum( (1 - paid) * amount) amount_owed
from debts
you can use conditional aggregation using select case.
SELECT
sum(case when paid = 0 then amount else 0 end) as not_paid
,sum(case when paid > 0 then amount else 0 end) as paid
FROM debts
SELECT user, paid, SUM(amount) total FROM debts GROUP BY user, paid
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.
I want to query an orders table and show the customer id and the total of all his orders, however the orders can have positive or negative totals.
select customer_id, SUM(order_total) from orders group by customer_id;
Now my question - how can I achieve the following in one sql query:
If the total sum is positive, I want to display it as is; if the total sum is negative, I just want to display 0 instead the actual amount.
What I am looking for is a function that can handle this, similar to the IFNULL function (IFNULL(SUM(order_total),0)), but instead of checking for null, it should check for a negative result.
Pseudo code:
IFNEGATIVE(SUM(order_total),0)
Is there a simple way in standard sql (or specifically in Mysql 5.5, would also be ok).
SELECT customer_id,
CASE
WHEN SUM(order_total) < 0 THEN 0
ELSE SUM(order_total)
END
FROM orders
GROUP BY customer_id;
Check your execution plan, but the 2 SUMs will probably be optimized to a single SUM under the hood.
Try with:
select customer_id, GREATEST( SUM(order_total),0) from orders group by customer_id;
Not tested, but something like this should do it:
SELECT customer_id , IF( SUM(order_total) > 0, SUM(order_total), 0) AS sum FROM orders GROUP BY customer_id
Could you not use a CASE statement?
Something like:
CASE WHEN [Field] < 0 THEN 0
Or did I miss something?
if i understand its only wrap it with GREATEST
SELECT customer_id, GREATEST(0,SUM(order_total))
FROM orders GROUP BY customer_id;
look on the link
select Id,case when (sum(amount)<0) then 0 else sum(amount) end from tblsum group by Id
You can also try;
select
(sum(fld) + abs(sum(fld))) / 2
from tbl
To only display positive Use HAVING thus:
select customer_id, SUM(order_total) from orders group by customer_id HAVING SUM(order_total) > 0;
Otherwise use case as listed elsewhere here
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