Sql. Different row number. No PL/SQL - sql

Good day.
In my work I found a little problem. I think that I'm worse SQL-man. I can't solve two days.
I have a little sql table consist of informathion of students, classes and schools like
I need the serial number for each new (class and school) for each student in each class. Without PL/SQL
School Class Name
first 1b Smith
first 1b Jones
first 1b Willams
second 1a Taylor
second 1b Brown
second 1b Davies
And Table I need
Number School Class Name
1 first 1b Smith
2 first 1b Jones
3 first 1b Willams
1 second 1a Taylor
1 second 1b Brown
2 second 1b Davies

I know you solved it but I think anybody looking this up wants to see the full solution
SQL Fiddle Demo: http://sqlfiddle.com/#!4/a6756/8
SELECT
row_number() over (partition BY school, class ORDER BY school, class) as nr
, s.*
from students s
Now the counting of rows only is by school and class.
Whenever I deal with analytical functions I have to scratch my head a bit and usually refer always to this page which I find an excellent tutorial and memory refresher: http://www.orafaq.com/node/55
Edit:
Following the remark from Clockwork-Muse I have removed the remark about what the order bywithin the analytical function does and quote the Oracle documentation:
http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions004.htm#i81407
order_by_clause
Use the order_by_clause to specify how data is ordered within a
partition. For all analytic functions you can order the values in a
partition on multiple keys, each defined by a value_expr and each
qualified by an ordering sequence.

Related

SQL: Find minimal occurence of a specific value

I have trouble exactly explaining what my problem is. Let me start with what I am NOT asking: I am NOT asking for the minimal value of a column.
Assume the following table, which in one column lists names and in the other column lists guesses estimating the age of the person on the left. Multiple people are guessing so there are different guesses:
Name
AgeGuess
Max
34
Jennifer
21
Jordan
88
Max
29
Jennifer
22
Jordan
22
Jordan
36
...
...
and so on and so on. My question is: What is an SQL command that could give me a table filled by all names who were guessed the LEAST to be for example 36 (must be a specific value !). Additionally I'd like also like to know how often they were guessed 36. If nobody guessed them 36 I'd like to know that too.
In this example only Jordan was guessed to be 36. All the others were never guessed to be 36. I would expect an output like this:
Name
GuessedToBe36Count
Max
0
Jennifer
0
The table above is the result of me asking which people were guessed to be 36 the least amount of times.
My attempt was to group them by how often they were guessed 36. However if they were never rated 36, they also do not appear in the table at all, meaning I cannot just compute the minimum of the column.
If you want to get count of guessed ages by each user, group by user
SELECT name, COUNT(ageGuess) AS total, ageGuess FROM user_guess GROUP BY name, ageGuess ORDER BY name, total ASC
You will get then something similar to this:
name
total
ageGuess
Jordan
1
33
Jordan
3
65
Max
1
34
Please note that it will not return not guessed values. You can fill-in it when processing in back-end.
To have your wanted output, do it with sub-query:
SELECT name, (SELECT COUNT(ageGuess) FROM guesses g2 WHERE g2.name = g1.name AND ageGuess = 36) FROM guesses g1 GROUP BY name
Example

Merge SQL Rows in Subquery

I am trying to work with two tables on BigQuery. From table1 I want to find the accession ID of all records that are "World", and then from each of those accession numbers I want to create a column with every name in a separate row. Unfortunately, when I run this:
Select name
From `table2`
Where acc IN (Select acc
From `table1`
WHERE source = 'World')
Instead of getting something like this:
Acc1
Acc2
Acc3
Jeff
Jeff
Ted
Chris
Ted
Blake
Rob
Jack
Jack
I get something more like this:
row
name
1
Jeff
2
Chris
3
Rob
4
Jack
5
Jeff
6
Jack
7
Ted
8
Blake
Ultimately, I am hoping to download the data and somehow use python or something to take each name and count the number of times it shows up with each other name at a given accession number, and furthermore measure the degree to which each pairing is also found with third names in any given column, i.e. the degree to which they share a cohort. So I need to preserve the groupings which exist with each accession number, but I am struggling to find info on how one might do this.
Could anybody point me in the right direct for this, or otherwise is the way I am going about this wise if that is my end goal?
Thanks!
This is not a direct answer to the question you asked. In general, it is easier to handle multiple rows rather than multiple columns.
So, I would recommend that you put each acc value in a separate row and then list the names as an array:
select t2.acc, array_agg(t2.name order by t2.name) as names
from `table2` t2
where t2.acc in (Select t1.acc
From `table1` t1
where t1.source = 'World'
)
group by t2.acc;
Otherwise, you are going to have a challenge just naming the columns in your result set.

Is it possible to select a column followed by a wildcard (to retrieve all columns) in SQL?

This might be a weird question, but I'll ask it anyway. When I'm working on queries, I'm usually interested in only a few particular columns at first and when I'm happy with the result, I'll add other columns to the query.
In other words: first I make it work, then I'll add the details. But I usually end up writing another query (that retrieves all table data) just above my "work-in-progress-query" in order to look at column names and inspect the data at a glance. It would be nice if that extra "retrieve all query" wasn't necessary and if I could just use a wildcard directly.
To state it simple: I'd like to do:
SELECT column, * from myTable;
So let's say I've got a table Person:
id name description number categoryId modified created
---------------------------------------------------------------------------------
1 Sven Ugly man 42 67 2014-03-03 2014-03-03
2 Anna Pretty woman 25 33 2014-03-03 2014-03-03
Then I would like to do:
SELECT number, * from Person
Which should be leading to:
number id name description number categoryId modified created
--------------------------------------------------------------------------------------
67 1 Sven Ugly man 42 67 2014-03-03 2014-03-03
33 2 Anna Pretty woman 25 33 2014-03-03 2014-03-03
Is such a thing possible?
Yes it is possible, and used frequently when testing.
Its not encouraged, as the * results in messy returns with columns sharing names. (especially duplicated columns, refrences and keys etc)
Short answer Yes, but not sensible

Maximum Value from multiple tables

I am a high school math teacher and my school's "data specialist." I am self-taught in Microsft Exel and Access, and I have been recently learning some of the SQL query language behind my usual Access work. I am comfortable with using Access queries to tie together data from many sources, such as exam scores from one source, English proficiency from a second source, and home phone number from a third source.
Here is a situation that I do not know how to do in Microsoft Access.
My math students take the New York state examination up to 3 times a year. They need a score of 80 to be considered "college ready."
Here are 3 sample tables. Each table uses the unique primary key "StudentID." The Integrated Algebra exam has the code MXRE.
Table #1 name: JanuaryAlgebra
StudentID Course Mark
201 MXRE 90
202 MXRE 55
203 MXRE 67
204 MXRE 80
205 MXRE 78
Note: Student #201 and #204 have finished the exam and do not take it again.
Table #2 name: JuneAlgebra
StudentID Course Mark
202 MXRE 70
203 MXRE 76
205 MXRE 81
206 MXRE 86
207 MXRE 78
There are two new students to the school, #206 and #207. Students #205 and #206 have finished the exam with high scores, and the remaining three students try the exam a third time.
Table #3 name: AugustAlgebra
StudentID Course Mark
202 MXRE 72
203 MXRE 83
207 MXRE 93
How do I return a query with one line for each StudentID displaying their highest exam score after the end of the school year???
Thanks!
Jeff
I'm not as familiar with Access, but I think it supports T-SQL. If it does then you can select all the rows in one statement and get the max. Though I realized when writing this answer that it's probably easier with a sub-select
In SQL it would look something like:
SELECT StudentId, Course, Max(Mark)
FROM (
SELECT StudentId, Course, Mark FROM JanuaryAlgebra
UNION
SELECT StudentId, Course, Mark FROM JuneAlgebra
UNION
SELECT StudentId, Course, Mark FROM AugustAlgebra
) as NewTable
GROUP BY StudentId, Course
I would suggest altering the table structure:
YourTable (Student_ID,Course,Mark,Date)
Then you can simply query:
SELECT Student_ID,Course,MAX(Mark) AS Max_Mark
FROM YourTable
--WHERE Course = 'MXRE' --If you wanted only algebra results.
GROUP BY Student_ID,Course
Multiple tables of identical structure almost never makes sense.
You can however use your current format to do this by unioning together all your tables in a subquery.

Table structure of a student

I want a table structure which can store the details of the student like the below format.
If the student is in
10 th standard -> I need his aggregate % from 1st standard to 9th standard.
5 th standard -> I need his aggregate % from 1st standard to 4th standard.
1 st standard -> No aggregate % has to be displayed.
And the most important thing is ' we need to use only one table'. Please form a table structure with no redundant values.
Any ideas will be greatly appreciated......
No friends this is not a home work. This is asked in Oracle interview, conducted in Hyderabad day before yesterday '24th July, 2010',. He asked me the table structure.
He even did not asked me the query. He asked me how I will design the table. Please advice me.
id | name | grade | aggregate
This would do the trick, id is your primary key, name is students first last name, grade is what grade he is in and aggregate is aggregate % based on the grade.
Fro example some rows might be:
10 | Bill Cosby | 10 | 90
11 | Jerry Seinfeld | 4 | 60
Bill Cosby would have aggregate percent of 90 in grades 1-9, and jerry would have 60 in grades 1-3. In this case it is one table and boils down to you managing the rule of aggregation for this table, since it has to be one table.
If this is an interview question, it looks like they would like to check your knowledge on Nested Tables. Essentially you would have one column as roll number, and other column which is a nested table as Class and Percentage.