I’m trying to figure out how to count the values in more than one column.
It seem the first COUNT I do gives me the correct results but everything I’ve tried to get the second column count gives the wrong result.
For example, with the following two columns,
Q2 Q3
1 1
1 1
2 2
1 1
1 1
5 5
3 5
5 3
4 1
2 2
3 3
3 3
5 5
3 3
2 1
2 1
3 2
4 1
1 1
1 1
2 2
5 5
3 3
2 1
3 3
1 1
2 1
SELECT COUNT(Q2) AS QU2 FROM mytable GROUP BY Q2
QU2 = 7 7 7 2 4
gives me the count for Q2. 7 one’s, 7 two’s and so on...
However, the following gives me an unexpected result.
SELECT COUNT(Q2) AS QU2, COUNT(Q3) AS QU3 FROM mytable GROUP BY Q2, Q3
7 4 3 1 5 1 2 1 3
I think its something with the GROUP BY but I don’t know how to get around it to get the needed result.
So I'm tying to get the result of
QU2 = 7 7 7 2 4
QU3 = 13 4 6 4
Or
QU2 QU3
7 13
7 4
7 6
2 4
4
and so on for QU4 QU5 ... I would appreciate any help.
Thank you
I think that this will get you closest to what you want. You can replace the numbers table with any method that generates the numbers 1 to whatever the max value is in Q2 or Q3.
CREATE TABLE dbo.Numbers (num INT)
INSERT INTO dbo.Numbers (num) VALUES (1), (2), (3), (4), (5)
SELECT
N.num,
SUM(CASE WHEN MT.Q2 = N.num THEN 1 ELSE 0 END) AS QU2,
SUM(CASE WHEN MT.Q3 = N.num THEN 1 ELSE 0 END) AS QU3
FROM
dbo.Numbers N
CROSS JOIN dbo.My_Table MT
GROUP BY
N.num
Adding additional columns (for Q4, etc.) just means adding another SUM(CASE...)
How GROUP BY works?
Let's talk about your first query (I added the column Q2 in the SELECT clause to make its output more clear):
SELECT Q2, COUNT(*) AS QU2
FROM mytable
GROUP BY Q2
First, it gets all the rows matching the WHERE criteria, if a WHERE clause exists. Because your query doesn't have a WHERE clause, all the rows from the table are read.
On the next step the rows read on the previous step are grouped by the expression specified in the GROUP BY clause (let's assume it contains only one expression, as the query above does). Internally, grouping the rows requires sorting them first.
This is how the data is organized on this step. I added horizontal separators between the rows that go in each group to make everything clear:
Q2 Q3
-------
1 1
1 1
1 1
1 1
1 1
1 1
1 1
-------
2 1
2 1
2 1
2 1
2 2
2 2
2 2
-------
3 2
3 3
3 3
3 3
3 3
3 3
3 5
-------
4 1
4 1
-------
5 3
5 5
5 5
5 5
-------
On the next step, from each group it creates a single row that goes to the generated result set.
The query above clearly returns:
Q2 QU2
--------
1 7
2 7
3 7
4 2
5 4
What happens when the GROUP BY clause contains more than one expression?
Let's take your second query (again, I added some columns to show its behaviour):
SELECT Q2, Q3, COUNT(*) AS cnt
FROM mytable
GROUP BY Q2, Q3
It works similar with the previous query but, because the GROUP BY clause contains two expression, each group created for the values of Q2 is split in sub-groups based on the value of Q3. Assuming there is another expression (let' say, Q4) in the GROUP BY clause, each sub-group created for a pair (Q2, Q3) is further divided into sub-groups for all the values of Q4 and so on.
For your table, the groups and sub-groups are as follows:
Q2 Q3
=======
1 1
1 1
1 1
1 1
1 1
1 1
1 1
=======
2 1
2 1
2 1
2 1
---
2 2
2 2
2 2
=======
3 2
---
3 3
3 3
3 3
3 3
3 3
---
3 5
=======
4 1
4 1
=======
5 3
---
5 5
5 5
5 5
=======
I used double lines to separate the groups and smaller single lines to separate the subgroups inside each group.
The output of this query is:
Q2 Q3 cnt
------------
1 1 7
2 1 4
2 2 3
3 2 1
3 3 5
3 5 1
4 1 2
5 3 1
5 5 3
How to get the desired result?
It is not possible to get the result you want using a single query. Even more, the result sets you suggest doesn't make much sense.
You can combine two queries using UNION in order to get the data you need and additional information that helps you know where those numbers come from:
SELECT 'Q2' AS source, Q2 AS q, COUNT(Q2) AS cnt FROM mytable GROUP BY Q2
UNION
SELECT 'Q3' AS source, Q3 AS q, COUNT(Q3) AS cnt FROM mytable GROUP BY Q3
The output is:
source q cnt
----------------
Q2 1 7
Q2 2 7
Q2 3 7
Q2 4 2
Q2 5 4
Q3 1 13
Q3 2 4
Q3 3 6
Q3 5 4
Pretty clear, isn't it? The first 5 rows come from the query GROUP BY Q2 and their value in the column q tells what was the value of Q2 for each group (there are 7 occurrences of 1 in column Q2, 7 of 2, 7 of 3, 2 of 4 and so on). The last 4 rows tell the similar story about Q3 (13 rows have 1 in column Q3 and so on).
Remark
There is a difference between COUNT(*) and COUNT(Q2): COUNT(*) counts the rows from the group, COUNT(Q2) counts the not-NULL values in the column Q2. It doesn't care about duplicate, it only ignore the NULL values. If you want to count the distinct values then you have to add the DISTINCT keyword: COUNT(DISTINCT Q2).
I think you need to unpivot the data. In this case, that just means multiple group by connected by union all:
select 'q2' as which, q2, count(*) as cnt
from mytable
group by q2
union all
select 'q3' as which, q3, count(*) as cnt
from mytable
group by q3;
You can add as many more subqueries as you like.
Note: this puts the values in separate rows, rather than in separate columns.
I reckon Asaph is on the right track , however I would alter this slightly try select distinct count(Q2) as QU2, count(Q3) as QU3 from myTable;
Related
Assume I have table count and the column is (nilai, id_courses, id_lecturer)
nilai id_courses id_lecturer
----- ---------- -----------
2 1 1
2 1 1
2 1 1
3 1 1
3 1 1
1 2 1
1 2 1
5 2 1
5 2 1
then I want to create view like this :
nilai id_courses id_lecturer count
----- ---------- ----------- -----
2 1 1 3
3 1 1 2
1 2 1 2
5 2 1 2
how to do that in SQL syntax?
I just know how to count 1 value with this code
SELECT COUNT( nilai ) , id_courses, id_lecturer FROM count where nilai=1
I've read this post but its to complex, so I don't know how it's work
You need to count all distinct entries by grouping them. The query
SELECT nilai, id_courses, id_lecturer, COUNT(*) AS count
FROM count GROUP BY nilai, id_courses, id_lecturer
should exactly return the table you posted.
I'm stuck with the following problem.
I have a website with for example supermarket shopping items. People can search the website for items.
Now I want on the search result page at the top 2 items to be displayed that I have selected to be on offer. There can be lots more items on offer.
So for example, someone would search for shampoo, the query would display all the shampoo items in the database table but I want just 2 shampoo offer items at the top of the query. There could be 2 or more shampoo offers in the database table, then the other would just not be shown.
Example with names :
Table:
id name C D
----------------------------------
1 Jack 1 1
2 Joe 1 1
3 Dave 3 0
4 Sue 1 0
5 Mike 1 1
6 Steve 4 0
7 David 1 0
8 Susan 4 1
9 Marc 1 1
10 Ronald 4 1
11 Michael 4 1
EXAMPLE 1
Query :
WHERE C = 1 AND D = 1 (But only maximum of 2 'D' records, these 2 'D' records show at the top of the result)
Desired Query Result :
id name C D
----------------------------------
1 Jack 1 1
2 Joe 1 1
4 Sue 1 0
7 David 1 0
EXAMPLE 2
Query :
WHERE C = 4 AND D = 1 (But only maximum of 2 'D' records, these 2 'D' records show at the top of the result)
Desired Query Result :
id name C D
----------------------------------
8 Susan 4 1
10 Ronald 4 1
6 Steve 4 0
I hope this explains my goal what I'm trying to achieve.
Many thanks for any help or suggestions!
That's two queries that you can combine with UNION ALL:
select * from mytable where c = 1 and d = 1 limit 2
union all
select * from mytable where c = 1 and d = 0
order by d desc;
UPDATE: If you want to have the two rows chosen randomly, then order by RAND(). (Without an ORDER BY the rows are chosen arbitrarily, which means it's not guaranteed to get the same two rows picked again when re-running the query ‐ but it's quite likely.) As we need an ORDER BY for a partial query (the first query in the complete union-alled query), we must use parentheses, because otherwise only one ORDER BY would be allowed, namely for the complete query at the query's end.
(select * from mytable where c = 1 and d = 1 order by rand() limit 2)
union all
(select * from mytable where c = 1 and d = 0)
order by d desc;
SQL fiddle: http://sqlfiddle.com/#!9/ed53f6/3.
This question already has answers here:
Returning the 'last' row of each 'group by' in MySQL
(6 answers)
Closed 7 years ago.
I have following table structure:
id customer_id version_num
1 1 1
2 1 2
3 2 1
4 2 2
5 3 1
6 3 2
7 3 3
I want results to be displayed as:
id customer_id version_num
2 1 2
4 2 2
7 3 3
I'm able to get the following results:
id customer_id version_num
1 1 1
3 2 1
5 3 1
Query that I used:
select * from TABLE group by customer_id
I don't know how to make use of latest(version_num) in my query.
SELECT Y.id, Y.customer_id, Y.version_num
FROM YourTable Y
JOIN (SELECT customer_id, MAX(version_num) max_v
FROM YourTable
GROUP customer_id
) T
ON Y.customer_id = T.customer_id
AND Y.version_num = T.max_v;
I have this table:
ID STUDENT CLASS QUESTION ANSWER TIME
1 1 1 1 c 12:30
2 1 1 1 d 12:36
3 1 1 2 a 12:38
4 2 1 1 b 11:24
5 2 1 1 c 11:26
6 2 1 3 d 11:35
7 2 3 3 b 11:24
I'm trying to write a query that does this:
For each STUDENT in a specific CLASS select the most recent ANSWER for each QUESTION.
So, choosing class "1" would return:
ID STUDENT CLASS QUESTION ANSWER TIME
2 1 1 1 d 12:36
3 1 1 2 a 12:38
5 2 1 1 c 11:26
6 2 1 3 d 11:35
I've tried various combinations of subqueries, joins, and grouping, but nothing is working. Any ideas?
You can use a sub-query to get most recent ANSWER per QUESTION, Then use this as a derived table and join back to the original table:
SELECT m.*
FROM mytable AS m
INNER JOIN (
SELECT STUDENT, QUESTION, MAX(`TIME`) AS mTime
FROM mytable
WHERE CLASS = 1
GROUP BY STUDENT, QUESTION
) AS d ON m.STUDENT = d.STUDENT AND m.QUESTION = d.QUESTION AND m.`TIME` = d.mTime
WHERE m.CLASS = 1
Demo here
I need to select user_id & quiz_id, for users which their count of questions in their quiz = sum of correct, this mean they answer 100% correct
answers table:
quiz_id question_id user_id answer_id correct
1 1 1 1 1
1 2 1 6 0
1 3 1 9 1
2 1 2 1 1
2 2 2 5 1
3 4 1 17 1
3 5 1 21 1
3 6 1 25 1
4 1 3 1 1
5 4 4 18 0
6 1 5 1 1
6 2 5 5 1
7 1 3 2 0
7 2 3 7 0
ex 1:
user 1 took "quiz_id" = 1
count of questions in "quiz_id = 1" = 3
sum of correct = 2
so it's not 100%
user_id = 1 in quiz_id = 1 => will not selected
but user_id = 1 will be selected with quiz_id = 3 cause he got 100%
expected results:
quiz_id user_id
2 2
3 1
4 3
6 5
notes:
quiz could be taken with different users with different number of
questions
quiz_id, user_id unique together (user can not take same quiz twice)
thanks,
You should use an aggregate query with HAVING clause:
SELECT quiz_id, user_id
FROM quiz_answer -- or whatever the name is
GROUP BY quiz_id, user_id
HAVING COUNT(question_id) = SUM(correct)
here you must use HAVING instead of WHERE because
The HAVING clause can refer to aggregate functions, which the WHERE
clause cannot
as specified in the docs.