SQL Basic Select Statement: Exercise-24 with Solution
From the following table, write a SQL query to find the details of 1970 Nobel Prize winners. Order the result by subject, ascending except ‘Chemistry’ and ‘Economics’ which will come at the end of result set. Return year, subject, winner, country, and category.
Solution
SELECT *
FROM nobel_win
WHERE year=1970
ORDER BY
CASE
WHEN subject IN ('Economics','Chemistry') THEN 1
ELSE 0
END ASC,
subject,
winner;
SQL Basic Select Statement: Exercise-23 with Solution.
In this solution, year is in front of DESC. I'm confused. Does the order of ASC,DESC and the column title matter? Like the one in exercise 24, both subject and winner are put after ASC. Are they both in ascending order?
In SQL to order the result in ascending or descending, we have to put ASC or DESC keyword after the column name that we need to sort. For example, in Exercise 24 the ASC keyword is after the order by statement. This means the result is in ascending order according to your case.
In exercise 23 the DESC keyword is after the year. This means the result is ordered in descending order considering the year column.
So as a conclusion the keywords ASC and DESC are used after the field name that we want to arrange in order.
Check this link for more details about orders by ASC and DESC.
Related
I am trying to show the most popular TV show in each country. However, the resulting table outputs multiple shows from the same country, if I include the column that has the shows name. If I don't include this column, it correctly outputs the MAX for eacg country, but without the show name. Can I include both?
This is the script that gets the result I want without the names.
SELECT
origin_country, MAX(popularity) as Most_popular
FROM TV_data
WHERE origin_country not like '%(%'
GROUP BY origin_country
order by Most_popular DESC
This is the script that results in multiple shows from the same country, since the name column is grouped as well.
SELECT
origin_country, name, MAX(popularity) as Most_popular
FROM TV_data
WHERE origin_country not like '%(%'
GROUP BY origin_country, name
order by Most_popular DESC
Thnka you, still learning SQL so any advice is greatly appreciated.
Your idea is correct to GROUP BY origin_country and use MAX to find the highest popularity per country.
All you need to do now is to put this in a subquery, build a main query which shows the other columns, too and JOIN them:
SELECT
tv1.origin_country,
tv1.name,
tv1.popularity Most_Popular
FROM tv_data tv1
JOIN (
SELECT origin_country, MAX(popularity) popularity
FROM tv_data
GROUP BY origin_country) tv2
ON tv1.origin_country = tv2.origin_country
AND tv1.popularity = tv2.popularity
WHERE tv1.origin_country NOT LIKE '%(%'
ORDER BY tv1.popularity DESC;
The above query will be executed on every DB.
Today, DB's usually provide window functions for that as another and maybe easier option. The exact syntax for this way depends on the DB you use since functions often differ between OracleDB, MYSQL DB etc.
Here is an example for a SQLServer DB using RANK:
SELECT
origin_country,
name,
popularity Most_Popular
FROM (SELECT origin_country,
name,
popularity,
RANK() OVER(PARTITION BY origin_country ORDER BY popularity DESC) dest_rank
FROM tv_data) sub
WHERE dest_rank = 1
AND origin_country NOT LIKE '%(%'
ORDER BY popularity DESC;
The PARTITION BY clause works like the GROUP BY in the first query.
If you change for example the condition dest_rank = 1 to dest_rank < 3, you will get the two most popular shows per country.
Try out here: db<>fiddle
From the following table, write a SQL query to find the Nobel Prize winners for the subject not started with the letter 'P'. Return year, subject, winner, country, and category. Order the result by year, descending.
Sample table : nobel_win
Solution:
SELECT *
FROM nobel_win
WHERE subject NOT LIKE 'P%'
ORDER BY year DESC, winner;
I don't understand why the solution put winner at the end. It seems that winner is not required.
Most likely, the winner column was tagged to the end of the ORDER BY clause to break the tie should 2 or more records happen to have the same year. If that be the case, then simply ordering by year descending might leave all records belonging to a given year appearing unsorted. The query you posted above resolves this by ordering all record within a given year by the winner name.
I have a table with two columns name and age. I want to keep the names clumped together but order the clumps by the clump containing the youngest age.
Merlot 12
Cab 8
Merlot 6
Cab 10
I want to perform a query resulting in...
Merlot 12
Merlot 6
Cab 8
Cab 10
How would you perform this SQL query?
You can use window functions:
order by min(age) over (partition by name),
name
It is very important to use name as the second key. This handles the case where two names have the same minimum -- the rows for the names are guaranteed to be separated.
I assume there is some kind of ID column, as Merlot is sorted in age descending, and Cab ascending; so something you haven't shown us is determining that order. Anyway, you can do this with a window function:
ORDER BY MIN(Age) OVER (PARTITION BY [name]) ASC,
YourID ASC;
Try adding this expression to the order by... either in a subquery or the outer query... you don't have to ultimately select it.
row_number() over (partition by name order by age)
You need to order by age as well. Add this to the end of your query might do the trick
ORDER BY name, age
I have a table in oracle 10g and I want to get the last value of specified column of a table based on some conditions. How to write the query for this in NetBeans for exp. Suppose I want to get the last value of balance column where student id = 101, class = nursery and academic year = 2014
You can use ROWNUM to limit the number of results.
And to get the last records, you have to sort the records based on your condition.
An example of your query can be.
select * from (
select * from student
where class='nursery' and academic_year=2014
order by id desc
) where ROWNUM=1;
This will sort the records in DESCENDING order by id and returns the first record from the results.
Updated
As mentioned by MT0 in comments, ROWNUM value will be assigned before ORDER BY clause. Thus, may result in incorrect result.
I have corrected the above query, and now
subquery will sort the records in descending order of id.
selection will be done on the results. (WHERE ROWNUM=1)
Starting with oracle 10g you can use the LAST_VALUE function. Assuming if "balance" per student can be ordered by some time variable, and if student_id is unique within academic_year, class:
SELECT student_id, academic_year,class, LAST_VALUE(balance) OVER
(PARTITION BY student_id, academic_year,class ORDER BY time_variable desc) AS
last_balance from student where student_id ...;
The first row of this query contains the most recent value of "balance" (last_balance)
I am using a little bit different query. Don't know why, but always put rownum in subquery as a new column
select m.* from (
select rownum as rn, t.* from student t
where t.class='nursery' and t.academic_year=2014
order by t.di desc) m
where m.rn=1;
Can you LIMIT a query from the end of the results, rather than from the beginning? In particular, I'm looking for a solution w/ Postgresql, if that makes a difference.
Allow me to clarify with an example.
Let's say I want to return the 3 oldest people in my people table, but in ascending order of age. The best way I know how to select the 3 people returns the correct records, but in the reverse order:
SELECT * FROM people
ORDER BY age DESC
LIMIT 2
should be this way-
SELECT * FROM (
SELECT *
FROM PEOPLE
ORDER BY AGE DESC
LIMIT 3 ) X
ORDER BY AGE ASC