Select distinct count over two columns - sql

I have data that looks like this:
school district crs_sbj crs_num crs_sec
CANYON HIGH IRON DISTRICT ENGL 2010 213
CANYON HIGH IRON DISTRICT ENGL 2010 214
CANYON HIGH IRON DISTRICT ENGL 1010 110
CANYON HIGH IRON DISTRICT MATH 1010 400
WAYNE HIGH WAYNE DISTRICT MATH 1010 321
WAYNE HIGH WAYNE DISTRICT MATH 1010 322
WAYNE HIGH WAYNE DISTRICT ENGL 1010 500
I want to count the unique classes offered at each individual high school.
For example, I want to see:
count school
3 CANYON HIGH
2 WAYNE HIGH
How would I go about doing this? I understand the concept of one column, but how about two?

Try this:
select school, count(distinct crs_num) _count
from table
group by school;

Select School, count(distinct crs_num)
from table
group by School

I am unsure what constitutes a unique class.
; with aardvark (select distinct school, district, crs_sbj, crs_num
from T)
select district, school, count(*)
from aardvark
group by school, district
Since the same school name can be used across districts, I included the district in the grouping.

Related

Oracle 11g - select only one row for each town in a table

I have a table with 300K records, but only ~100 unique town names. I need sql to return 1 row for each individual town name. Table structure:
UNIQUE_ID
STREET_NUMBER
STREET_NAME
STREET_TYPE
TOWN
ZIP
UID01
11
TROY
STREET
ASHFIELD
2017
UID02
13
ABED
ROAD
ASHFIELD
2017
UID03
2
FRANK
COURT
EMERTON
2021
UID04
8
DENNIS
GROVE
SACKVILLE
2028
UID05
97
MAC
CRESCENT
SACKVILLE
2028
UID06
102
CHARLIE
WALK
SACKVILLE
2028
UID07
70
DEE
BOULEVARD
WINDSOR
2033
UID08
27
POPPY
STREET
WINDSOR
2033
UID09
33
ALLY
WAY
BARGO
2315
UID10
48
ELS
AVENUE
BARGO
2315
I'm trying to get the data returned to be something like:
UNIQUE_ID
STREET_NUMBER
STREET_NAME
STREET_TYPE
TOWN
ZIP
UID01
11
TROY
STREET
ASHFIELD
2017
UID03
2
FRANK
COURT
EMERTON
2021
UID04
8
DENNIS
GROVE
SACKVILLE
2028
UID07
70
DEE
BOULEVARD
WINDSOR
2033
UID09
33
ALLY
WAY
BARGO
2315
Don't care which record is returned for each town name, but need one record for each town.
I've trawled through various similar posts but can't seem to get the syntax correct.
I'm able to select each individual town name using this:
select min(TOWN) keep (dense_rank first order by rownum) TOWN
from ADDRESS_TABLE group by TOWN;
But not sure how to get the other attached data to return as well.
Help please?
If you don't care about which one to take, then take any of them (e.g. first by unique_id):
WITH
temp
AS
(SELECT unique_id,
street_number,
street_name,
street_type,
town,
zip,
ROW_NUMBER () OVER (PARTITION BY town ORDER BY unique_id) rn
FROM address_table)
SELECT unique_id,
street_number,
street_name,
street_type,
town,
zip
FROM temp
WHERE rn = 1

Change column values to column headers in Postgres SQL replacing with values from another column

I am unable to figure out how to make a column values into column headers and assign appropriate values as it happens
Say I have a Postgres database with the following table:
Name Subject Score Region
======= ========= ======= =======
Joe Chemistry 20 America
Robert Math 30 Europe
Jason Physics 50 Europe
Joe Math 70 America
Robert Physics 80 Europe
Jason Math 40 Europe
Jason Chemistry 60 Europe
I want to select/fetch data in the following form:
Name Chemistry Math Physics Region
======= ========== ======= ======== ========
Joe 20 70 null America
Robert null 30 80 Europe
Jason 60 40 50 Europe
Considering that there are 80 subjects. How do I write an SQL select statement that returns data in this format?
In Postgres, I recommend using the FILTER syntax for conditional aggregation:
SELECT name,
MAX(score) FILTER (WHERE subject = 'Chemistry') AS Chemistry,
MAX(score) FILTER (WHERE subject = 'Math') AS Math,
MAX(score) FILTER (WHERE subject = 'Physics') AS Physics
FROM grades
GROUP BY name

Loop through a table based on multiple conditions

Students table
student_id student_name
1 John
2 Mary
Grades table
student_id year grade_level school Course Mark
1 2015 10 Smith High Algebra 95
1 2015 10 Smith High English 96
1 2016 11 Smith High Geometry 85
1 2016 11 Smith High Science 88
2 2015 10 Smith High Algebra 98
2 2015 10 Smith High English 93
2 2016 11 Smith High Geometry 97
2 2016 11 Smith High Science 86
I'm trying to show results for each year and what class a student took with the grade.
So the final output i'm looking for is something like:
[student_id1] [year1] [grade1] [school1]
[course1] [mark1]
[course2] [mark2]
[course3] [mark3]...
[student_id1] [year2] [grade2] [school1]
[course1] [mark1]
[course2] [mark2]
[course3] [mark3]...
[student_id2] [year1] [grade1] [school1]
[course1] [mark1]
[course2] [mark2]
[course3] [mark3]...
This would all go in one column/row. So in this particular example, this would be my result:
1 2015 10 Smith High
Algebra 95
English 96
1 2016 11 Smith High
Geometry 85
Science 88
2 2015 10 Smith High
Algebra 98
English 93
2 2016 11 Smith High
Geometry 97
Science 86
So anytime a student id, year, grade, or school name changes, I would have a line for that and loop through the classes taken within that group. And all of this would be in one column/row.
This is what I have so far but I'm not sure how I can properly loop through course and grades for each group. I'd appreciate it if I can be pointed in the right direction.
select s.student_id + '' + year + '' + grade_level + '' + school
from students
join grades on students.student_id = grades.student_id
If you want to do it in your SQL Enviromnment, it depends on the Database Management System you are using.
For example, if you are using Transact SQL you can try to look at this link.
Generally this kind of loops and interactions are done in the programming language that is coupled with the SQL DB.
Anyway, you should look at Stored Procedures and Cursors if you really want to do this in SQL.
You are trying to mix presentation with retrieval of data from database tables. Looping through the resultset in sql can be achieved via cursor but that isn't adviced. You are better off by pulling the required data using two queries and later print it using a language of your choice.

How to SELECT rows that has same values in column 1 but different values in column 2?

I have this query below:
I've managed to filter out the names with the SAME YEAR but DIFFERENT TID, then how to I pick these names out without duplication?
OUTPUT:
OK the desire output should be like this per request.
firstname | lastname | year | tid
Alex Hannum 1956 MI1
Alex Hannum 1956 ROC
Alex Hannum 1956 STL
Alex Hannum 1956 SYR
Alvin Attles 1969 PH1
Alvin Attles 1969 SFW
Alvin Attles 1970 PH1
Alvin Attles 1970 SFW
Andrew Levane 1952 MI1
Andrew Levane 1952 ROC
Andrew Levane 1952 SYR
.... and so on.
I think you are looking for the players who opt-out two or more tid in a year,
If so you can use the below query on the data you displayed in screen-shot assuming it also has one more column which identify players uniquely.
SELECT firstname,lastname,year,tid FROM player where player_id in (select distinct player_id from player group by firstname,lastname,year having count(*) >1)

VBA/SQL recordsets

The project I'm asking about is for sending an email to teachers asking what books they're using for the classes they're teaching next semester, so that the books can be ordered. I have a query that compares the course number of this upcoming semester's classes to the course numbers of historical textbook orders, pulling out only those classes that are being taught this semester. That's where I get lost.
I have a table that contains the following:
Professor
Course Number
Year
Book Title
The data looks like this:
professor year course number title
--------- ---- ------------- -------------------
smith 13 1111 Pride and Prejudice
smith 13 1111 The Fountainhead
smith 13 1222 The Alchemist
smith 12 1111 Pride and Prejudice
smith 11 1222 Infinite Jest
smith 10 1333 The Bible
smith 13 1333 The Bible
smith 12 1222 The Alchemist
smith 10 1111 Moby Dick
johnson 12 1222 The Tipping Point
johnson 11 1333 Anna Kerenina
johnson 10 1333 Everything is Illuminated
johnson 12 1222 The Savage Detectives
johnson 11 1333 In Search of Lost Time
johnson 10 1333 Great Expectations
johnson 9 1222 Proust on the Shore
Here's what I need the code to do "on paper":
Group the records by professor. Determine every unique course number in that group, and group records by course number. For each unique course number, determine the highest year associated. Then spit out every record with that professor+course number+year combination.
With the sample data, the results would be:
professor year course number title
--------- ---- ------------- -------------------
smith 13 1111 Pride and Prejudice
smith 13 1111 The Fountainhead
smith 13 1222 The Alchemist
smith 13 1333 The Bible
johnson 12 1222 The Tipping Point
johnson 11 1333 Anna Kerenina
johnson 12 1222 The Savage Detectives
johnson 11 1333 In Search of Lost Time
I'm thinking I should make a record set for each teacher, and within that, another record set for each course number. Within the course number record set, I need the system to determine what the highest year number is - maybe store that in a variable? Then pull out every associated record so that if the teacher ordered 3 books the last time they taught that class (whether it was in 2013 or 2012 and so on) all three books display. I'm not sure I'm thinking of record sets in the right way, though.
My SQL so far is basic and clearly doesn't work:
SELECT [All].Professor, [All].Course, Max([All].Year)
FROM [All]
GROUP BY [All].Professor, [All].Course;
Use your query as a subquery and INNER JOIN it back to the [ALL] table to filter the rows.
SELECT
a.Professor,
a.Year,
a.Course,
a.title
FROM
[ALL] AS a
INNER JOIN
(
SELECT [All].Professor, [All].Course, Max([All].Year) AS MaxOfYear
FROM [All]
GROUP BY [All].Professor, [All].Course
) AS sub
ON
a.Professor = sub.Professor
AND a.Course = sub.Course
AND a.Year = sub.MaxOfYear;