This question already has answers here:
Aggregate ad clicks and views
(2 answers)
Closed 3 years ago.
Say I have a table log with format [prodName, status]
An example set be:
| ProdName | Status
|-----------------------
| AXD1 | 100
| BL1 | 100
| AXD2 | 300
| BL2 | 300
| AXD1 | 300
| AXD2 | 100
| BL1 | 100
| BL1 | 100
I will the result group by status where 100 is success and 300 not. So the result like this.
| ProdName | Success | Not
|-----------------------
| AXD1 | 1 | 1
| BL1 | 3 | 0
| AXD2 | 1 | 1
| BL2 | 0 | 1
You could use case expressions to find if a row was a success or not, and then count them:
SELECT ProdName,
COUNT(CASE Status WHEN 100 THEN 1 END) AS "Success",
COUNT(CASE Status WHEN 300 THEN 1 END) AS "Not Success"
FROM mytable
GROUP BY ProdName
You can use conditional aggregation:
select
ProdName,
sum(Status = 100) Success,
sum(Status = 300) `Not`
from Log
group by ProdName
See the demo.
Results:
| ProdName | Success | Not |
| -------- | ------- | --- |
| AXD1 | 1 | 1 |
| AXD2 | 1 | 1 |
| BL1 | 3 | 0 |
| BL2 | 0 | 1 |
Related
I'm having a problem.
I have this table called usersbycourse which shows this information:
+------------+-----------------+--------+-----------+-------+-----------------+-----------------+
| instanceid | shortname | userid | firstname | logid | lastaccessdelta | modulesfinished |
+------------+-----------------+--------+-----------+-------+-----------------+-----------------+
| 2 | PJU | 74 | Robin | 766 | 1662246 | 0 |
| 3 | Fundgest-GRHN1A | 75 | Batman | 867 | 1576725 | 0 |
| 3 | Fundgest-GRHN1A | 77 | Abigobeu | 1004 | 610480 | 0 |
+------------+-----------------+--------+-----------+-------+-----------------+-----------------+
and this SQL:
SELECT
mdl_course.id,
mdl_course.shortname,
COUNT(CASE WHEN usersbycourse.modulesfinished = 1 THEN NULL ELSE 1 END) AS studentcount
FROM mdl_course LEFT JOIN usersbycourse ON mdl_course.id = usersbycourse.instanceid
GROUP BY mdl_course.id;
The results from the SQL are:
+----+-----------------+--------------+
| id | shortname | studentcount |
+----+-----------------+--------------+
| 1 | Unity I | 1 |
| 2 | PJU | 1 |
| 3 | Fundgest-GRHN1A | 2 |
| 4 | asdzxc2 | 1 |
+----+-----------------+--------------+
But why? In inside SQL has no Unity I, and no asdzxc2. How do I produce a result like this:
+----+-----------------+--------------+
| id | shortname | studentcount |
+----+-----------------+--------------+
| 1 | Unity I | 0 |
| 2 | PJU | 1 |
| 3 | Fundgest-GRHN1A | 2 |
| 4 | asdzxc2 | 0 |
+----+-----------------+--------------+
?
EDIT:
I want to count only rows having modulesfinished = 0
What you're looking for is SUM rather than COUNT, that is,
SELECT
mdl_course.id,
mdl_course.shortname,
SUM(CASE WHEN usersbycourse.modulesfinished = 0 THEN 1 ELSE 0 END) AS studentcount
FROM mdl_course LEFT JOIN usersbycourse ON mdl_course.id = usersbycourse.instanceid
GROUP BY mdl_course.id;
The problem is because you are using LEFT JOIN some of the values for usersbycourse.modulesfinished are NULL
Something you need to learn is
NULL == something
Is always unknown, not true, not false, just unknown.
So when you try to compare with = 1 your nulls get the ELSE but not because they aren't 1, is because is all the rest.
So if instead you change the condition to
COUNT(CASE WHEN usersbycourse.modulesfinished = 0 THEN 1 ELSE NULL)
Only the TRUE match will get 1, the FALSE and the UNKNOW part ill get NULL and COUNT doesnt count nulls. And that is what you want.
I have a table 'questions' with columns
userid
qid(question id)
answer
The questions are multiple choice so not every question has the same number of answers a user can choose from.
question 100 might have 4 answers to choose from.
question 200 might have 6 answers to choose from.
question 300 might have 2 answers to choose from.
etc
So the table might look something like this:
+-------- --+---------+--------+
| userid | qid | answer |
+---- ------+---------+--------+
| 1 | 100 | 4 |
| 1 | 200 | 6 |
| 1 | 300 | 1 |
| 1 | 400 | 4 |
| 2 | 100 | 1 |
| 2 | 400 | 6 |
| 3 | 200 | 4 |
| 3 | 400 | 4 |
| 3 | 100 | 1 |
| 4 | 100 | 1 |
| 4 | 400 | 6 |
| 5 | 200 | 1 |
| 5 | 400 | 6 |
+-----------+---------+--------+
I want to know what's the count for the most given answer for question 100, what's the count for the second highest answer for question 100 , what's the count for the 3rd highest answer for question 100, etc
I've can't figure how to query this and not sure if this is possible.
I would the results to be something like:
+------+----+----+----+----+----+----+----+
| qid |ans1|ans2|ans3|ans4|ans5|ans6|ans7|
+------+----+----+----+----+----+----+----+
| 100 | 3 | 0 | 0 | 1 | 0 | 0 | 0 |
| 200 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| 300 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| 400 | 0 | 2 | 0 | 0 | 0 | 3 | 0 |
+------+----+----+----+----+----+----+----+
Group by the questions and then you can use aggregate functions like sum() that apply to each group. And you can use a condition in sum() to do conditional summing
select qid,
sum(answer = 1) as ans1,
sum(answer = 2) as ans2,
sum(answer = 3) as ans3,
sum(answer = 4) as ans4,
sum(answer = 5) as ans5,
sum(answer = 6) as ans6,
sum(answer = 7) as ans7,
count(*) as total
from your_table
group by qid
I have 2 tables bellow
0 --> Pending
1 --> Success
2 --> Fail
table : mntnc
+-------+-------+-------+
| id | own | sts |
+-------+-------+-------+
| 1 | BN | 1 |
| 2 | BB | 2 |
| 3 | BN | 1 |
| 4 | BD | 1 |
| 5 | BD | 0 |
table : istlsi
+-------+-------+-------+
| id | own | sts |
+-------+-------+-------+
| 1 | BN | 1 |
| 2 | BB | 1 |
| 3 | BB | 1 |
| 4 | BC | 0 |
| 5 | BD | 2 |
of the two tables above, I want to add both of them to be the table below
+-------+-----------+-----------+-----------+
| own | success | fail | pending |
+-------+-----------+-----------+-----------+
| BN | 3 | 0 | 0 |
| BB | 2 | 1 | 0 |
| BD | 1 | 1 | 1 |
| BC | 0 | 0 | 1 |
The two key points here:
Union tables (I aliased result to B)
Use sum(case...) for each column.
First we union both tables together as an inline view.
We then use a case statement for each desired column and evaluate the status setting the value to 1 or 0 depending on sts value. and then sum those...
SELECT own
, sum(case when sts=1 then 1 else 0 end) as Success
, sum(case when sts=2 then 1 else 0 end) as Fail
, sum(case when sts=0 then 1 else 0 end) as Pending
FROM ( SELECT ID, own, sts
FROM mntnc
UNION ALL
SELECT id, own, sts
FROM istlsi
) B
GROUP BY own
I have a table which store user votes, something like this:
+----+---------+-------+---------+
| id | post_id | value | user_id |
+----+---------+-------+---------+
| 1 | 103 | 1 | 1 |
| 2 | 105 | 1 | 3 |
| 3 | 106 | 1 | 1 |
| 4 | 108 | 0 | 1 |
| 5 | 108 | 0 | 2 |
| 6 | 105 | 0 | 2 |
| 7 | 105 | 1 | 1 |
+----+---------+-------+---------+
Where id is Vote ID, post_id is Post ID, value is a boolean for like/unlike (1 = Like, 0 = Unlike) and user_id is Voter ID.
I want to get a list which has:
All posts
Each post's like count
Each post's unlike count
Vote ID of where a user (for example, user 1) voted. So I can update the value later
The vote that user gave
So I wrote this query:
SELECT
post_id,
COUNT(
CASE
WHEN value = 1
THEN 1
END
) AS likes,
COUNT(
CASE
WHEN value = 0
THEN 1
END
) AS unlikes,
(CASE
WHEN user_id = 1 -- I choose user_id manually
THEN id
END) AS vote_id,
(CASE
WHEN user_id = 1
THEN value
END) AS user_vote
FROM votes
GROUP BY post_id;
What I expected was something like this:
+---------+-------+---------+---------+-----------+
| post_id | likes | unlikes | vote_id | user_vote |
+---------+-------+---------+---------+-----------+
| 103 | 1 | 0 | 1 | 1 |
| 105 | 2 | 1 | 7 | 1 |
| 106 | 1 | 0 | 3 | 1 |
| 108 | 0 | 2 | 4 | 0 |
+---------+-------+---------+---------+-----------+
But this is the result I have:
+---------+-------+---------+---------+-----------+
| post_id | likes | unlikes | vote_id | user_vote |
+---------+-------+---------+---------+-----------+
| 103 | 1 | 0 | 1 | 1 |
| 105 | 2 | 1 | NULL | NULL |
| 106 | 1 | 0 | 3 | 1 |
| 108 | 0 | 2 | 4 | 0 |
+---------+-------+---------+---------+-----------+
Those NULL values happen because of the last line of my query (GROUP BY post_id). If there's a duplicate post_id in table (for example, if some other user already voted for that post), CASE will ignore it and return NULL.
What should I do?
The problem with your query is the lack of aggregations on the last two columns. Assuming that a user can only vote once for a post, you are safe combining the values using MAX() (or MIN()) because there is at most one matching row:
SELECT v.post_id, SUM(value = 1) AS likes, SUM(value = 0) AS unlikes,
MAX(CASE WHEN user_id = 1 THEN vote_id END) AS user1_voteid,
MAX(CASE WHEN user_id = 1 THEN value END) AS user1_vote
FROM votes v
GROUP BY v.post_id;
I have a query and a result as follows.
In the database NULL and 0 represent the same meaning.
Now I want a counter based on Null+0 or 1
Eg:in the following example I want the result like this:
IsVirtual Category counter
NULL+0 3 343+8 = (351 is Total)
Query
select * from
(
Select IsVirtual, Category, count(*) as counter
from [Hardware]
group by IsVirtual, Category
) innercat
Output
+-----------+----------+---------+
| IsVirtual | Category | counter |
+-----------+----------+---------+
| NULL | 3 | 343 |
| 0 | 3 | 8 |
| 1 | 2 | 1 |
| 0 | 1 | 1 |
| NULL | 6 | 119 |
| 0 | 4 | 1 |
| NULL | 1 | 70 |
| 0 | 5 | 9 |
| NULL | 4 | 54 |
| 0 | 2 | 2 |
| NULL | 5 | 41 |
| NULL | 2 | 112 |
| 1 | 1 | 5 |
+-----------+----------+---------+
I think you want this :
SELECT COALESCE(IsVirtual, 0) as [IsVirtual],
Category,
Count(*) as [Counter]
FROM yourtable
GROUP BY COALESCE(IsVirtual, 0),Category
This will give you expected result without using subquery.
try with this
select * from (
Select CASE ISNULL(IsVirtual,0)
WHEN 0 Then 'NULL + 0'
ELSE IsVirtual
END AS IsVirtual, Category, count(*) as counter from [Hardware] group by ISNULL(IsVirtual,0), Category
)innercat
You can also do the same thing by using MAX function
This might help you.
SELECT
max(IsVirtual) as IsVirtual,
Category,
Count(*) as Counter
FROM
yourtable
GROUP BY
Category