I have an MYSQL database table of student info and their test scores per subject and I am trying to fetch each student's highest score in all subjects using the SQL query below
SELECT DISTINCT
first_name,
last_name,
subject_id,
(SELECT
MAX(score)
FROM
cbt_attempts_tbl
WHERE
first_name = first_name) AS MAX_SCORE
FROM
cbt_attempts_tbl
WHERE
score IS NOT NULL
ORDER BY first_name DESC
sample data
After running the query, the result I get are not as expected
In your subselect you need to link both tables, for example by using an alias
SELECT DISTINCT
first_name,
last_name,
subject_id,
(SELECT
MAX(score)
FROM
cbt_attempts_tbl
WHERE
first_name = f1.first_name) AS MAX_SCORE
FROM
cbt_attempts_tbl f1
WHERE
score IS NOT NULL
ORDER BY first_name DESC
But I don't really know what you are searching for, but following give the same, as DISTINCT doesn't make sense as long you don't have multiple rows with the same subject_id and name combination
SELECT
first_name,
last_name,
subject_id,
(SELECT
MAX(score)
FROM
cbt_attempts_tbl
WHERE
first_name = f1.first_name) AS MAX_SCORE
FROM
cbt_attempts_tbl f1
WHERE
score IS NOT NULL
GROUP BY first_name,
last_name,
subject_id
ORDER BY first_name DESC
If you are not worried about students without any score , then your query would be like
SELECT first_name, last_name, subject_id, MAX(score) FROM cbt_attempts_tbl GROUP BY first_name, last_name, subject_id ORDER BY first_name DESC
Otherwise, if you want to keep a full student list, you need to make a left joined query like
SELECT DISTINCT t.first_name, t.last_name, scores.subject_id, scores.subject_max_score FROM cbt_attempts_tbl t LEFT JOIN (SELECT first_name, last_name, subject_id, MAX(score) AS subject_max_score FROM cbt_attempts_tbl GROUP BY first_name, last_name, subject_id) scores ON scores.first_name = t.first_name AND scores.last_name = t.last_name GROUP BY t.first_name, t.last_name, scores.subject_id ORDER BY t.first_name DESC
At last, if to be more comprehensive, your database design is not correct. You should have a students table and your cbt_attempts_tbl table should have a foreign key student_id that references a students table id column. And then it would be completely different query - select from students left joined by cbt_attempts_tbl on foreign key condition
Related
I have a table like this:
with each row representing a review given by a user. I want to get the users by the number of distinct cities they wrote reviews in. For example:
cities, users
1,1012388
2,221758
which means that 1012388 users wrote reviews for businesses in one city only.
I tried:
select count(distinct(city)) as city, count(user_id)
from table1
group by user_id
order by count(user_id) desc
First you need to find the number of distinct city reviews that each user wrote:
SELECT user_id, COUNT(DISTINCT city) AS num_reviews
FROM table1
GROUP BY user_id
Then you can group that data by number of reviews:
SELECT num_reviews, COUNT(user_id) AS num_users
FROM (SELECT user_id, COUNT(DISTINCT city) AS num_reviews
FROM table1
GROUP BY user_id) r
GROUP BY num_reviews
ORDER BY num_users DESC
I need to find duplicate uses based on either same email OR first_name, last_name combination OR same birth_date. What I could comfortably try was:
SELECT id, first_name, last_name
FROM users
where id IN (SELECT id
from users
GROUP BY email
HAVING count(*) > 1)
GROUP BY email, id;
The above gives only duplicate email details, but I'm bit confused about handling other conditions based on first_name, last_name combination OR same birth_date as well.
Is it possible to achieve it in a single query?
Try doing a UNION of three separate queries which checks for the three duplicate criteria:
SELECT id
FROM users
GROUP BY id
HAVING COUNT(DISTINCT email) > 1
UNION
(
SELECT id
FROM users t1
INNER JOIN
(
SELECT firstname, lastname
FROM users
GROUP BY firstname, lastname
HAVING COUNT(*) > 1
) t2
ON t1.firstname = t2.firstname AND
t1.lastname = t2.lastname
)
UNION
SELECT id
FROM users
GROUP BY id
HAVING COUNT(DISTINCT birthdate) > 1
I have the following query :
SELECT directory_auth_id, first_name, last_name, COUNT(user_info.directory_auth_id) as Duplication
FROM user_info
GROUP BY directory_auth_id, first_name, last_name
HAVING COUNT(*) > 1
ORDER BY directory_auth_id ASC
This gives me the desired results and shows me all records that meet the criteria.. What it does not do, is show me ALL the records.. How do I see all records that have been matched.
Thanks,
Boardman.
Assuming the SQL Server tag is correct, the best approach is to use window functions:
select ui.*
from (select ui.*, count(*) over (partition by directory_auth_id, first_name, last_name) as cnt
from user_info ui
) ui
where cnt > 1
order by cnt desc, directory_auth_id, first_name, last_name;
Unfortunately, MySQL does not support this ANSI standard functionality. But there are other approaches to solving the problem.
For SQL Server only...
To display all rows related only to the directory_auth_id that exist more than once, you have to determine which directory_auth_id have duplication, then use that resultset as a filter on the main table.
This will accomplish that.
;WITH DUPES
AS
(
SELECT directory_auth_id
FROM user_info
GROUP BY directory_auth_id
HAVING COUNT(*) > 1
)
SELECT directory_auth_id, first_name, last_name
FROM user_info T1
JOIN DUPES T2 ON T1.directory_auth_id = T2.directory_auth_id
This may work for you.
SELECT * FROM user_info where (directory_auth_id,first_name,last_name) in (
SELECT directory_auth_id, first_name, last_name
FROM user_info
GROUP BY directory_auth_id, first_name, last_name
HAVING COUNT(*) > 1
)
ORDER BY directory_auth_id ASC
Try the following, this puts your query into an inline view and then joins to it based on the three relevant fields. So you would get all records from user_info that have more than one line for a (directory_auth_id, first_name, last_name) combination.
select x.*
from user_info x
join (select directory_auth_id,
first_name,
last_name,
count(*) as duplication
from user_info
group by directory_auth_id, first_name, last_name
having count(*) > 1) y
on x.directory_auth_id = y.directory_auth_id
and x.first_name = y.first_name
and x.last_name = y.first_name
This is for MSSQL:
select
directory_auth_id,
first_name,
last_name,
case when count(user_info.directory_auth_id)
over (partition by directory_auth_id, first_name, last_name) > 1
then count(user_info.directory_auth_id)
over (partition by directory_auth_id, first_name, last_name)
end as Duplication
from user_info;
I have a table with this format
first_name last_name
and I want to show the pairs of "first_name" and "last_name" that appear exactly twice at the database. I've used this
select first_name, last_name, count(*)
from employees
having count(*)=2;
which is wrong and I am not sure what it's doing. It's my first sql approach so please be patient :) *Working with mysql workbench
You need a group by:
select first_name, last_name, count(*)
from employees
group by first_name, last_name
having count(*)=2;
select first_name, last_name, count(*)
from employees
group by first_name, last_name
having count(*)=2;
You have to use group by and then using having clause for this..
Query is:
select first_name, last_name, count() from employees group by first_name, last_name having count()=2;
So I have a table called members and another table called group.The leader of the group is also a member
To retrieve members,who are not leaders I did the following
code:
SELECT first_name, last_name, rank
FROM members
EXCEPT ALL
SELECT first_name, last_name, rank
FROM members INNER JOIN groups ON mid=leader; --edited gid as mid
Doing this in MySQL gives me a syntax error.What should I use for EXCEPT ALL in MySQL?
SELECT first_name, last_name, rank
FROM members
LEFT OUTER JOIN groups ON gid=leader
WHERE leader is null
Not sure if leader or gid is in the groups table. The column that is in the groups table must have a null check in the where clause.
subquery may do, something like:
SELECT first_name, last_name, rank
FROM members
WHERE id NOT IN (
SELECT leader
FROM groups
WHERE leader = members.id
)
We need to know your table structure to help you further
You can try with this scenario.
SELECT
r.col1,r.col2
FROM tabel1 r
WHERE ROW ( r.col1,r.col2 ) NOT IN(
SELECT
col1,col2
FROM tabel2
);