This question already has answers here:
Retrieving last record in each group from database - SQL Server 2005/2008
(2 answers)
Closed 4 years ago.
I'm not sure how to word my question so perhaps an example would be best. I'm looking for a function or statement that would produce the following result from a single table. For each name, return the row with largest id.
ID NAME ADDRESS
1 JOHN DOE 123 FAKE ST.
2 JOHN DOE 321 MAIN ST.
3 JOHN DOE 333 2ND AVE.
4 MARY JANE 222 1ST. AVE
5 MARY JANE 444 POPLAR ST.
6 SUZY JO 999 8TH AVE.
DESIRED RESULT
3 JOHN DOE 333 2ND AVE.
5 MARY JANE 444 POPLAR ST.
6 SUZY JO 999 8TH AVE.
One option is to use the row_number window function. This allows you to establish a row number to the result set. Then you can define the grouping and ordering within the over clause, in this case you want to partition by (group) the name field and order by the id field descending. Finally you filter those results where rn = 1 which returns the max result for each grouping.
select *
from (
select *, row_number() over (partition by name order by id desc) rn
from yourtable
) t
where rn = 1
Related
How can I sort by number first and further sort same number names by alphabet?
Example:
Score | Name
-----------
12 John
11 Paul
10 Dave
9 Adam
9 Ben
9 David
Just use the SQL syntax for ordering by multiple columns:
order by Score, Name
Select * from Table Order by Score , Name
I'm having a table similar to this:
first
last
date
pos
john
doe
18-03-2021
harris
potter
10-06-2021
john
doe
10-05-2021
harris
potter
14-06-2021
jessica
potter
14-06-2021
kermit
foster
The use case is as follow:
The pos column correspond to a positive covid test
The date column correspond to the vaccination date
To be elligible for a covid certificate, some one must either:
Been tested positive and have got 1 vaccine
Have receive 2 vaccine
I'm trying to write a query that return me:
totalDose, totalRequieredDose
For exemple:
If he has tested positive, the totalRequiredDose is 1 and if he has got 1 vaccine, he is elligible. As such, for Harry Potter, totalDoses=1 and totalRequieredDoses=1 and is elligible
If he has not been tested positive, the totalRequiredDose is 2 and if he has got 2 vaccines, he is elligible. As such, for John Doe, totalDoses=2 and totalRequieredDoses=2 and is elligible
first
last
totalDoses
totalRequieredDoses
john
doe
2
2
harris
potter
1
1
jessica
potter
1
2
kermit
foster
0
2
As Jessica Potter have a vaccine and no pos date, she must have 2 vaccines.
So the value 1/2
And Kermit foster have no pos value, he is 0/2
Etc.
I'm scratching my head to write a query (or pl/sql) that could return me such table.
Could someone give me some hints ?
We can aggregate by first and last name. The total doses is simply the count of non NULL vaccination dates. For the total required number of doses, we can start with a value of 2. This value can then be offset by 1 assuming there exists a non NULL date for the pos column, indicating that a given person tested positive at some point.
SELECT
first,
last,
COUNT(date) AS totalDoses,
2 - (COUNT(*) FILTER (WHERE pos IS NOT NULL) > 0)::int AS totalRequieredDoses
FROM yourTable
GROUP BY
first,
last
ORDER BY
COUNT(date) DESC,
first,
last;
Demo
This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed 1 year ago.
Assume that I have one table looking like this:
ID
ClientID
Name
Country
1
JX100
John
Canada
2
JX100
John
Japan
3
JX690
Rob
EUA
4
PX301
Alice
France
And My query:
SELECT DISTINCT ClientID,Name,Country FROM CLIENTS
OUTPUT:
ClientID
Name
Country
JX100
John
Canada
JX100
John
Japan
JX690
Rob
EUA
PX301
Alice
France
I want to take that:
DESIRED:
ClientID
Name
Country
JX100
John
Canada
JX690
Rob
EUA
PX301
Alice
France
TL;DR
I just want to select one country for all Clients, I don't want to get repeated rows.
You can use row_number()over() with common table expression like below:
with cte as (
SELECT DISTINCT ClientID,Name,Country,row_number()over(partition by ClientID ,Name order by Country) rownumber FROM CLIENTS)
select * from cte where rownumber=1
Row_number()over(partition by ClientID ,Name order by Country) will generate a sequence for contries starting from 1 against each clientid and name. So when you will select rownumber=1 this query will select one country for a single clientid,name combination.
So I have this query:
SELECT
Search.USER_ID,
Search.SEARCH_TERM,
COUNT(*) AS Search.count
FROM Search
GROUP BY 1,2
ORDER BY 3 DESC
Which returns a response that looks like this:
USER_ID SEARCH_TERM count
bob dog 50
bob cat 45
sally cat 38
john mouse 30
sally turtle 10
sally lion 5
john zebra 3
john leopard 1
And my question is: How would I change the query, so that it only returns the top 2 most-searched-for-terms for any given user? So in the example above, the last row for Sally would be dropped, and the last row for John would also be dropped, leaving a total of 6 rows; 2 for each user, like so:
USER_ID SEARCH_TERM count
bob dog 50
bob cat 45
sally cat 38
john mouse 30
sally turtle 10
john zebra 3
In SQL Server, you can put the original query into a CTE, add the ROW_NUMBER() function. Then in the new main query, just add a WHERE clause to limit by the row number. Your query would look something like this:
;WITH OriginalQuery AS
(
SELECT
s.[User_id]
,s.Search_Term
,COUNT(*) AS 'count'
,ROW_NUMBER() OVER (PARTITION BY s.[USER_ID] ORDER BY COUNT(*) DESC) AS rn
FROM Search s
GROUP BY s.[User_id], s.Search_Term
)
SELECT oq.User_id
,oq.Search_Term
,oq.count
FROM OriginalQuery oq
WHERE rn <= 2
ORDER BY oq.count DESC
EDIT: I specified SQL Server as the dbms I used here, but the above should be ANSI-compliant and work in Snowflake.
Below is my SQL Server 2012 query example. How do I add an extra column “StaffNo” to show an incremental integer?
This int always starts with 1, it doesn’t need to be matching with the staff name. for example “Joe” in this query running shows 1 in staff No, in next query running he could be 2 or 3 or any other number.
Same user always appear same staff No. Different user appear different No.
The number must be sequential and the increment is 1.
Because Staff is more than 100, so don’t write the query like “select case when staff = ‘Joe’ then 1 End”.
my query:
Staff CaseNumber
Joe 5880
Joe 4489
Joe 2235
Emily 7790
Emily 8813
expected result:
Staff CaseNumber StaffNo
Joe 5880 1
Joe 4489 1
Joe 2235 1
Emily 7790 2
Emily 8813 2
Use DENSE_RANK over the entire table, without a partiton, and order by the staff member's name.
SELECT
Staff,
CaseNumber,
DENSE_RANK() OVER (ORDER BY Staff) StaffNo
FROM yourTable;
Demo here:
Rextester