SUM of rows in My Sql with condition - mysql

My Data is
ID SCORE
1 55
1 -1
1 25
1 -1
1 -1
1 35
2 25
2 -1
2 65
2 55
2 21
2 -1
Now i want to add/sum the score of each id ignoring -1 and i am trying with this code which is not working
SELECT SUM(CASE when SCORE>-1 THEN SUM(SCORE) ELSE 0 END)
FROM jbit WHERE htno='$id'
Here i am already using WHERE so how can i use another WHERE, if i use multiple Where in single query it may effect other processes.. please help me out
Help me out friends

if there is only two column then there is no need to use SUM, you can try below
SELECT id, IF(SCORE=-1,0,SCORE) AS scoreSum
FROM table1
GROUP BY id
Working DEMO
alternative ( not tested )
SELECT id, SUM(IF(SCORE=-1,0,SCORE)) AS scoreSum
FROM table1
WHERE htno =$id
GROUP BY id

SELECT SUM(score) AS score_sum
FROM jbit
WHERE htno='$id'
AND score <> -1 ;

SELECT SUM(`SCORE`)
FROM `jbit`
WHERE `htno` = '$id'
`SCORE` > 0;
Though, I'd suggest you to change '$id' to just $id if the column type of htno is INTEGER.

SELECT SUM(score) FROM <tablename> WHERE score != -1

Related

sql calculate percentage over grouped data

I have a table X like this,
student ans_status question_id
1 1 10
2 -1 10
3 1 10
4 0 10
1 -1 11
2 1 11
3 -1 11
4 -2 11
expected o/p is
10 2/3
11 1/3
etc..
Now, i want the data fro each question 10 like,
number of 1's/(total of 1's and -1's for each question)
I have tried this,
select (select count(student_id) from X
where question_id=10 and ans_status=1) / count(student_id)
from X
where question_id=10
group by ans_status
having ans_status in(1,-1).
i can do it in a nested query, by again selecting and grouping according to the status condition, but is there any way better to do this?
please note i want this for all questions in the table
You can just do:
select question_id,
avg(ans_status = 1)
from X
where ans_status in (1, -1)
group by question_id;
This uses the MySQL feature that a boolean expression is treated as an integer in a numeric context. "True" is 1 and "false" is 0, so the average turns out to be the percentage that are true.
If you want the values independently:
select question_id,
sum(ans_status = 1), count(*)
from X
where ans_status in (1, -1)
group by question_id;
Use GROUP BY for taking count of each question_id for getting count of answer_id is 1 or -1.
Query
select t.`question_id`,
t.`count_1` / t.`total_count` as `new_col` from(
select `question_id`,
sum(case `ans_status` when 1 then 1 when -1 then 1 else 0 end) as `count_1`,
count(*) as `total_count`
from `your_table_name`
group by `question_id`
)t;
Find a demo here

How to get last item for GROUP BY [duplicate]

This question already has answers here:
Select last row in MySQL
(11 answers)
MySQL - Select the last inserted row easiest way
(9 answers)
Closed 5 years ago.
I have a table like this:
id transaction_id auto_recurring paid_amount package_customerid
37 0 1 0 4
45 37 1 0 4
51 0 1 0 4
57 51 1 0 4
62 0 1 0 4
67 62 1 0 4
There are 6 records of package_customer_id = 4. Now I want to get the last record of 4. in this case id = 67 is my desired record. I try this SELECT * FROM transactions GROUP BY package_customer_id. But I got first record of package_customer_id = 4. i.e: id = 4 is my fetched result. How can I get id = 67 (my desired record) modifying this sql?
SELECT * FROM transactions WHERE package_customer_id = 4 ORDER BY id DESC LIMIT 1;
That would be my shot at it. Sorry but i haven't tested it, i leave it up to you:)
EDIT:
Dont forget the quotes " ` " on columns name's:)
Check you column name package_customer_id OR package_customerid ?
You may try this .
SELECT temp.* FROM (SELECT * FROM `transactions` WHERE package_customer_id = 4 order by id DESC LIMIT 1 ) AS temp GROUP BY temp.package_customer_id
Don't use group by. Use where:
SELECT t.*
FROM transactions t
WHERE t.id = (SELECT MAX(t2.id)
FROM transactions t2
WHERE t2.package_customer_id = t.package_customer_id
);
You can filter this for whichever package customer ids you like, in the outer query.
You can use like this:
SELECT * FROM transactions WHERE id IN (SELECT MAX(id) FROM transactions GROUP BY package_customerid)
try this query
if you need with GROUP BY clause: use this query
SELECT * FROM transactions where GROUP BY package_customerid ORDER BY package_customerid DESC LIMIT 1;
OR
if you DON'T need with GROUP BY clause: use this query
SELECT MAX(id),transaction_id,auto_recurring,paid_amount,package_customerid FROM transactions where package_customerid=4;
Output:
id transaction_id auto_recurring paid_amount package_customerid
67 62 1 0 4

Get max and min values along with all values and multiple where clause

I have this query which works very good
SELECT cm.id ,cm.edited,cm.date_edited,cm.voteup,cm.votedown
FROM chat_messages cm
WHERE TIMESTAMPDIFF(SECOND,cm.date_edited,'$now') < 10 GROUP BY cm.id
Which gives me the entries which are edited in less then 10 seconds.
But along with that im trying to get also the max(voteup) and min(votedown)
But dont affect the first entries of the first query . How can i combine then to get all entries i need ?
Example:
if im getting 3 newly updates entries . i want to get them those 3 plus the max of voteup and votedown .
Example:
id edited date_edited voteup votedown
37 0 2016-03-05 22:13:03 5 0
38 0 2016-04-02 11:15:00 3 7
39 0 2016-03-05 22:10:06 10 6
40 0 2016-03-20 21:40:06 5 0
41 1 2016-04-20 22:28:59 5 0
42 1 2016-03-20 21:59:15 0 20
43 1 2016-04-21 22:20:25 8 0 <---- this new updated
My wished result is
id edited date_edited voteup votedown maxup maxdown
39 0 2016-03-05 22:10:06 10 6 10 NULL
42 1 2016-03-20 21:59:15 0 20 NUll 20
43 1 2016-04-21 22:20:25 8 0 NULL NULL
My $now time is 2016-04-21 22:20:20
explanation:
-id 39 is having maxup vote i want get it
-id 42 is having maxdown i want get it
-id 43 is newly updated in that period of 10 seconds.
so i general i want get new updated entries pls the max up and down .
if many max voteup values are same then just choose one which have min votedown
Any solution to that pls ?
Here my sqlfiddle example
Edit: oh sorry i meant id . now wish my question is clear like
you will want to use a UNION statement:
SELECT * FROM (
select cm.id ,cm.edited,cm.date_edited,cm.voteup,cm.votedown
, voteup as maxup, null AS maxdown
from chat_messages cm
ORDER BY voteup DESC, votedown
LIMIT 1
) a
UNION
SELECT * FROM (
select cm.id ,cm.edited,cm.date_edited,cm.voteup,cm.votedown
, null as maxup, votedown AS maxdown
from chat_messages cm
ORDER BY votedown DESC, voteup
LIMIT 1
) b
UNION
SELECT * FROM (
SELECT cm.id ,cm.edited,cm.date_edited,cm.voteup,cm.votedown
, null as maxup, null AS maxdown
from chat_messages cm
WHERE TIMESTAMPDIFF(SECOND,cm.date_edited,'2016-04-21 22:20:20') < 10
) c
note that I used '2016-04-21 22:20:20', but you will want to substitute the $now back in
you can use user-defined variables to track your maximums and then outer query the rows that match your rules.
SELECT id,edited,date_edited,voteup,votedown,
IF(voteup=#maxvoteup,voteup,NULL) as maxvoteup,
IF(votedown=#maxvotedown,votedown,NULL) as maxvotedown
FROM (SELECT cm.id ,cm.edited,cm.date_edited,cm.voteup,cm.votedown,
#maxvoteup := GREATEST(#maxvoteup,cm.voteup) as maxvoteup,
#maxvotedown := GREATEST(#maxvotedown,cm.votedown) as maxvotedown
FROM chat_messages cm,(SELECT #maxvoteup:=0,#maxvotedown:=0)initial
)T
WHERE TIMESTAMPDIFF(SECOND,date_edited,'2016-04-21 22:20:25') < 10
OR voteup = #maxvoteup
OR votedown = #maxvotedown
ORDER BY id ASC
sqlfiddle
Here's another query that is much more CRAZY..but it works ..
for maxupvote row, it'll find row that has maxupvote and minimum down vote, if more than 1 row exists (in a tie) it'll grab the row with latest/largest id.
for maxdownvote row, it'll find row that has maxdownvote and minimum up vote,
if more than 1 row exists (in a tie) it'll grab the row with latest/largest id.
SELECT id,edited,date_edited,voteup,votedown,
IF(voteup=#maxvoteup,voteup,NULL) as maxvoteup,
IF(votedown=#maxvotedown,votedown,NULL) as maxvotedown
FROM (SELECT cm.id ,cm.edited,cm.date_edited,cm.voteup,cm.votedown,
#minvotedown :=
(CASE WHEN cm.voteup > #maxvoteup OR (cm.voteup = #maxvoteup AND cm.votedown < #minvotedown)
THEN cm.votedown
ELSE #minvotedown
END),
#minvoteup :=
(CASE WHEN cm.votedown > #maxvotedown OR (cm.votedown = #maxvotedown AND cm.voteup < #minvoteup)
THEN cm.voteup
ELSE #minvoteup
END),
#maxvoteup := GREATEST(#maxvoteup,cm.voteup) as maxvoteup,
#maxvotedown := GREATEST(#maxvotedown,cm.votedown) as maxvotedown,
#maxvoteupid :=
(CASE WHEN cm.voteup = #maxvoteup AND cm.votedown = #minvotedown
THEN cm.id
ELSE #maxvoteupid
END),
#maxvotedownid :=
(CASE WHEN cm.votedown = #maxvotedown AND cm.voteup = #minvoteup
THEN cm.id
ELSE #maxvotedownid
END)
FROM chat_messages cm,(SELECT #maxvoteup:=0,#maxvotedown:=0,#minvoteup:=0,#minvotedown:=0,#maxvoteupid:=0,#maxvotedownid:=0)initial
ORDER BY cm.id ASC
)T
WHERE TIMESTAMPDIFF(SECOND,date_edited,'2016-04-21 22:20:25') < 10
OR id = #maxvoteupid
OR id = #maxvotedownid
ORDER BY id ASC;
sqlfiddle
I call it CRAZY because it is...if i was doing this. I would just run 3 separate queries
1 query to return one row with order by upvote DESC, downvote ASC, id DESC limit 1
1 query to return one row with order by downvote DESC, upvote ASC, id DESC limit 1
1 query to return one row that's within the last 10 seconds order by id DESC
this way it's much easier to maintain.

SQL Query - order by date but also group

OK Ladies and Gents, I would really appreciate some help:
This is my table:
ID postID replyID content entry_date
1 0 40 hey 12/7
2 0 40 hi 12/8
3 0 40 whatsup 12/9
4 2 40 why? 12/10
5 0 40 who? 12/11
I need to run a query to get it like this:
ID postID replyID content entry_date
1 0 40 hey 12/7
2 0 40 hi 12/8
4 2 40 why? 12/10
3 0 40 whatsup 12/9
5 0 40 who? 12/11
You will see that ID 3 and 4 have switched. So basically I need to ASC by entry_date, unless ID = POSTID, then I need those two grouped together and also ASC by entry_date for those two.
Here is what I have tried but I am totally lost:
SELECT t1.ID, t1.postID, t1.replyID, t1.content, t1.entry_date
FROM discussion t1, discussion t2
WHERE t1.replyID = '40' AND t1.ID = t2.postID
ORDER BY t1.entry_date ASC
Which basically does nothing but finds where a row of ID = a row of postID
You can add a CASE statement to your ORDER BY clause
ORDER BY
CASE WHEN postID = 0 THEN ID ELSE postID END
, entry_date
doing so, you can discard the join alltogether and the entire statement could be simplified to
SELECT ID
, postID
, replyID
, content
, entry_date
FROM discussion
ORDER BY
CASE WHEN postID = 0 THEN ID ELSE postID END
, entry_date
Note that I do assume the entry date being a DATETIME column, not a VARCHAR column.

mysql random with condition

I have a table in mysql, say table1.
I am running this on it:
SELECT FLOOR( MAX(id) * RAND()) FROM `table1`
This works well, but I am now trying to add a condition of "AND tom".
Where tom is a integer field.
For example:
id tom
1 0
2 3
3 2
4 0
5 0
6 3
7 1
8 1
9 3
etc.
So, my question is,
How can I pick a random value from id, which also satisfies tom='0' say?
SELECT id FROM `table1` WHERE tom = 0 ORDER BY RAND() LIMIT 1
This will first get all rows in which tom = 0,then order those results randomly. MySQL will then limit those results to just one, returning the single value you want to retrieve.
I hope I understood correctly:
SELECT id FROM `table1` WHERE tom = 0 order by rand() limit 1
select * from (
select * from table where tom = 0 ) as t order by rand() limit 1