How do I query this SQL table - sql

I am learning the SQL query and I have student subject table as below
ID
Subject
Date
One
English
30/01/2023
One
Science
28/01/2023
One
Maths
30/01/2023
One
Maths
29/01/2023
Two
Maths
30/01/2023
Two
Maths
29/01/2023
Three
Maths
30/01/2023
Four
Science
30/01/2023
Four
Maths
30/01/2023
Output:
I need to retrieve the IDs which contains only Maths subject as records as below
ID
Subject
Date
Two
Maths
30/01/2023
Two
Maths
29/01/2023
Three
Maths
30/01/2023
I tried the below but it retrieves the ID 1 and 4 also.
select *
from subject
where subject in ('Maths')

You can try this query:
select * from subject
where ID not in (select ID from subject where subject<>'Maths')

Try this query:
SELECT ID, Subject, Date
FROM subject
WHERE ID IN
(SELECT ID FROM subject
GROUP BY ID HAVING
count(case when Subject='Maths' then 1 end) = count(*))

Related

Learning SQL, trying to figure out how to get a gender count

I'm learning SQL and one of the questions that got thrown at me in my solo study suddenly is to write a script in order to count how many of each gender is in the client table,
Table CLIENT:
ClientID `First Name` `Last Name` Gender ID `Birth Date`
1 Sally Fields 1 03/05/2000
2 Hannah Montana 1 02/20/1989
3 Bart Simpson 2 02/03/1966
4 Michael Jordan 2 05/02/1970
5 Glennon Doyle 1 NULL
6 Lulu Jenkins 1 09/30/2001
Table GENDER:
ID `Gender Description`
1 Female
2 Male
I'm still very new to this so I'm stumped... the furthest I've gotten is:
SELECT
u.GenderID Gender,
COUNT(u.GenderID)
I'm not sure of where to go from there... the stuff I'm studying went from 1-100 really fast and I'm totally lost lol. Any guidance would be much appreciated!
Assuming you want to return the gender name and a count of each, simply join your two tables and aggregate, grouping by the gender description and counting the rows that belong to each grouping:
select g.`Gender Description`, Count(*) GenderCount
from client c
join gender g on g.id = c.GenderId
group by g.`Gender Description`;
Note the use of short meaningful aliases makes the query more compact and easy to read at a glance.
with GenderTable AS
(
SELECT
CASE
WHEN 'Gender ID'=1 Then 'Female'
Else 'Male'
END AS gender
FROM CLIENT
)
SELECT count(gender), gender
FROM GenderTable
GROUP BY gender
;
You can try this too using the Common Table Expression

SQLite query to get table based on values of another table

I am not sure what title has to be here to correctly reflect my question, I can only describe what I want.
There is a table with fields:
id, name, city
There are next rows:
1 John London
2 Mary Paris
3 John Paris
4 Samy London
I want to get a such result:
London Paris
Total 2 2
John 1 1
Mary 0 1
Samy 1 0
So, I need to take all unique values of name and find an appropriate quantity for unique values of another field (city)
Also I want to get a total quantity of each city
Simple way to do it is:
1)Get a list of unique names
SELECT DISTINCT name FROM table
2)Get a list of unique cities
SELECT DISTINCT city FROM table
3)Create a query for every name and city
SELECT COUNT(city) FROM table WHERE name = some_name AND city = some_city
4)Get total:
SELECT COUNT(city) FROM table WHERE name = some_name
(I did't test these queries, so maybe there are some errors here but it's only to show the idea)
As there are 3 names and 2 cities -> 3 * 2 = 6 queries to DB
But for a table with 100 cities and 100 names -> 100 * 100 = 10 000 queries to DB
and it may take a lot of time to do.
Also, names and cities may be changed, so, I can't create a query with predefined names or cities as every day it's new ones, so, instead of London and Paris it may be Moscow, Turin and Berlin. The same thing with names.
How to get such table with one-two queries to original table using sqlite?
(sqlite: I do it for android)
You can get the per-name results with conditional aggregation. As for the total, unfortunately SQLite does not support the with rollup clause, that would generate it automatically.
One workaround is union all and an additional column for ordering:
select name, london, paris
from (
select name, sum(city = 'London') london, sum(city = 'Paris') paris, 1 prio
from mytable
group by name
union all
select 'Total', sum(city = 'London'), sum(city = 'Paris'), 0
from mytable
) t
order by prio, name
Actually the subquery might not be necessary:
select name, sum(city = 'London') london, sum(city = 'Paris') paris, 1 prio
from mytable
group by name
union all
select 'Total', sum(city = 'London'), sum(city = 'Paris'), 0
from mytable
order by prio, name
#GMB gave me the idea of using group by, but as I do it for SQLite on Android, so, the answer looks like:
SELECT name,
COUNT(CASE WHEN city = :london THEN 1 END) as countLondon,
COUNT(CASE WHEN city = :paris THEN 1 END) as countParis
FROM table2 GROUP BY name
where :london and :paris are passed params, and countLondon and countParis are fields of the response class

SQL: Select distinct one column but include all fields

How can I select distinct one column (user) and then output the rest of the fields based on this one column?
Input:
user age country
--------------------------------
Tom 34 US
Tom 32 EN
Dick 29 MX
Dick 29 DE
Harry 15 CA
output (distinct user column, and pick one row to output for rest of fields):
user age country count
--------------------------------------
Tom 34 US 2
Dick 29 MX 2
Harry 15 CA 1
Any help would be appreciated!
SELECT USER, AGE, MAX(COUNTRY), COUNT(*)
FROM TABLE
GROUP BY USER, AGE
You could try changing the MAX for a MIN. No need for a DISTINCT here.
You could use some data format like SUBSTRING, but I'm not sure if the rest of the data will always be like that US and USS etc. Buy if you have more than 2/3 or if the changes start beyond a specific character you may encounter some wrong query results.
According to comments and updates.
SELECT USER, MAX(AGE), MAX(COUNTRY), COUNT(*)
FROM TABLE
GROUP BY USER.
SELECT user, age, country, COUNT(*) AS c_rec FROM
(
SELECT DISTINCT user, age, SUBSTRING(country, 1, 2) AS country FROM yourTable
) T
GROUP BY user, age, country

SQL - Query using Join / Having / Subquery - How

Please suggest a sql query to fetch the
"list of students and corresponding subject in which student has same score , if the student has same score in more than one subject"
eg.
Student Subject Score
John Science 80
John Maths 80
John English 80
John French 80
Peter Science 85
Peter Maths 70
Peter English 70
Peter French 70
Mathews French 70
Expected Result :
John Science
John Maths
John English
John French
Peter Maths
Peter English
Peter French
tried -
select person , subject where person in
( select person , score , count(score) group by person , score having count(score) > 1 )
but in this "Peter Science" appears , which is not required.
Please assist.
Thanks
Try:
select person , subject
from table t
join
( select person , score , count(score)
from table
group by person , score having count(score) > 1
) foo
on t.person = foo.person
where t.person = foo.person
and t.score = foo.score
The reason your query didn't work (aside from not including a table):
Your inner query was selecting the students and scores that match your criteria. But your outer query was selecting everything for all students who matched the criteria, which is why "peter science" was being included. So, you needed to limit the results in your outer query to only those that match all of your criteria.
You should tell us what RDBMS are you using. But this should work everywhere:
select
t.*
from <tableName> t
join (
select
student, score
from <tableName>
group by
student, score
having count(*)>1
) x
on t.student=x.student
and t.score=x.score
Btw you're missing FROM <tableName> in your query.
Try with this :
select student, subject
from Person
where student + cast(score as varchar(20)) in
(
select student + cast(score as varchar(20)) from Person group by student,score having count(score) > 1
)
You can achieve this goal self-joining table like in example:
SELECT
t.Student,
t.Subject,
t.Score
FROM Table1 AS t
JOIN
(
SELECT Student, Score FROM Table1 GROUP BY Student, Score HAVING COUNT(*) > 1
) AS t1 ON t.Student = t1.Student AND t.Score = t1.Score
Full example with test data and created table you can find here:
http://sqlfiddle.com/#!2/61f02/8

write a query to identify discrepancy

I have a table with Student ID's and Student Names. There has been issues with assigning unique Student Id's to students and Hence I want to find the duplicates
Here is the sample Table:
Student ID Student Name
1 Jack
1 John
1 Bill
2 Amanda
2 Molly
3 Ron
4 Matt
5 James
6 Kathy
6 Will
Here I want a third column "Duplicate_Count" to display count of duplicate records.
For e.g. "Duplicate_Count" would display "3" for Student ID = 1 and so on. How can I do this?
Thanks in advance
Select StudentId, Count(*) DupCount
From Table
Group By StudentId
Having Count(*) > 1
Order By Count(*) desc,
Select
aa.StudentId, aa.StudentName, bb.DupCount
from
Table as aa
join
(
Select StudentId, Count(*) as DupCount from Table group by StudentId
) as bb
on aa.StudentId = bb.StudentId
The virtual table gives the count for each StudentId, this is joined back to the original table to add the count to each student record.
If you want to add a column to the table to hold dupcount, this query can be used in an update statement to update that column in the table
This should work:
update mytable
set duplicate_count = (select count(*) from mytable t where t.id = mytable.id)
UPDATE:
As mentioned by #HansUp, adding a new column with the duplicate count probably doesn't make sense, but that really depends on what the OP originally thought of using it for. I'm leaving the answer in case it is of help for someone else.