Remove records based on priority in sql server - sql

details table
name age sports
john 27 football
john 27 cricket
john 27 basketball
kyle 28 baseball
kyle 28 football
nick 24 football
nick 24 hockey
ron 35 football
Priority table :
name priority
futsal 1
basketball 2
football 3
cricket 4
baseball 5
hockey 6
desired table :
name age sports
john 27 basketball --as basketball has the highest priority for john
kyle 28 baseball
nick 24 football
ron 35 football
What is desired is that i want to keep only 1 record for a name and rest should be deleted based on priority of sports .
I know to delete duplicate records but can anyone suggest me can this be accomplished in sql server and
how!!

Do the join use row_number():
select t.*
from (select d.name, d.age, d.sports,
row_number() over (partition by d.name order by p.priority) as seq
from details d inner join
priority p
on p.name = d.sports
) t
where seq = 1;

You can use window functions. Here is one method:
select dp.*
from (select d.*, min(p.priority) over (partition by d.name)
from details d join
priorities p
on d.sport = p.name
) dp
where seqnum = 1;

Related

Select unique countries with more than one customer

I need to show the countries that have more than one individual.
Customers
customer_id first_name last_name age country
1 John Doe 31 USA
2 Robert Luna 22 USA
3 David Robinson 22 UK
4 John Reinhardt 25 UK
5 Betty Doe 28 UAE
So the query should return
customer_id first_name last_name age country
1 John Doe 31 USA
2 Robert Luna 22 USA
3 David Robinson 22 UK
4 John Reinhardt 25 UK
I tried tis query but it didn't work.
SELECT last_name, Country
FROM Customers
GROUP BY Country
HAVING COUNT(Customer_id) > 1;
The actual table can be found here
Try using the following query. Thanks
SELECT * FROM CUSTOMERS C
WHERE C.COUNTRY IN (SELECT COUNTRY FROM CUSTOMERS GROUP BY COUNTRY HAVING COUNT(*)>1)
You could use a windowed count as a filter:
with c as (
select *, Count(*) over(partition by country) cnt
from Customers
)
select *
from c
where cnt > 1;

Group columns in query

I have a query where I fetch the following columns:
ID Name Age Hobby
ID, name and age comes from Table A
Hobby comes from Table B
Example of results I can get is the following:
ID Name Age Hobby
0 John 35 Fishing
0 John 35 Tennis
0 John 35 Hiking
1 Jane 31 Fishing
2 Nate 42 Fishing
2 Nate 42 Tennis
What I would like to have as result is the following instead:
ID Name Age Hobby
0 John 35 Fishing, Tennis, Hiking
1 Jane 31 Fishing
2 Nate 42 Fishing, Tennis
Any ideas of how to achieve that?
Try this :
;WITH CTE AS(
SELECT DISTINCT ID,NAME,AGE
FROM TableName
)
SELECT *,
STUFF(SELECT ','+ Hobby FROM TableName t1 WHERE t1.ID=CTE.ID FOR XML PATH(''),1,1,'')
FROM CTE

SQL statement to select an object that has multiple attributes in the same column

If I were given the following table ATHELTE
PLAYER_NAME SPORT_PLAYED YEAR_PLAYED
---------- ----------- ------------
BOB Basketball 2010
BOB Basketball 2011
BOB Basketball 2012
JOHN Basketball 2010
JOHN Soccer 2011
...
and I want to find a player who has played the same sports across multiple years (in this case it should return BOB since he played basketball for three years) what is the statement to reach the name?
Below is my attempt
SELECT DISTINCT PLAYER_NAME
FROM ATHLETE
HAVING count(YEAR_PLAYED > 1)
But for some reason it returns an empty set
select player_name, sport_played, count(*)
from athlete group by player_name, sport_played having count(*) > 1

How to retrieve same column twice from one table with Where condition

I am trying to retrieve a column twice from one table for ex:
select M.Event_Name as 'Male',
F.Event_Name as 'Female'
from Table1 M, Table1 F
where M.Gender = 'M'
and F.Gender = 'F'
and F.Country = 12
and M.Country = 12
Table1 data
ID Event_Name Gender Country
1 Cricket M 12
2 FootBall M 13
3 BasketBall M 12
4 Hockey M 12
5 Tennis M 13
6 Volly Ball M 13
7 Cricket F 13
8 FootBall F 13
9 BasketBall F 12
10 Hockey F 13
11 Tennis F 12
12 Volly Ball F 12
What I Got is :
Male Female
Cricket Tennis
Cricket BasketBall
Cricket Volly ball
BasketBall Tennis
BasketBall BasketBall
BasketBall Volly ball
Hockey Tennis
Hockey BasketBall
Hockey Volly ball
Expecting:
Male Female
Cricket Tennis
BasketBall BasketBall
Hockey Volly ball
Help me out.. Thanks
You should be able to use something like this which incorporates a PIVOT:
select M as Male,
F as Female
from
(
select event_name, gender,
row_number() over(partition by gender, country order by id) rn
from yourtable
where gender in ('M', 'F')
and country = 12
) src
pivot
(
max(event_name)
for gender in (M, F)
) piv
See SQL Fiddle with Demo
Or you can use an aggregate function with a CASE statement:
select
max(case when gender = 'M' then event_name end) male,
max(case when gender = 'F' then event_name end) female
from
(
select event_name, gender,
row_number() over(partition by gender, country order by id) rn
from yourtable
where gender in ('M', 'F')
and country = 12
) src
group by rn
See SQL Fiddle with Demo
Both produce the same result:
| MALE | FEMALE |
---------------------------
| Cricket | BasketBall |
| BasketBall | Tennis |
| Hockey | Volly Ball |

Joining multiple tables with a single query

Student
student_id FirstName LastName
---------------------------------------------------
1 Joe Bloggs
2 Alan Day
3 David Johnson
Student_Course
course_id student_id courseName
---------------------------------------------------
1 1 Computer Science
2 1 David Beckham Studies
3 1 Geography
1 3 Computer Science
3 3 Geography
Student_clubs
club_id student_id club_name club_count
---------------------------------------------------
1 1 Footbal 10
2 1 Rugby 10
3 1 Syncronized Swimming 10
4 3 Tennis 15
In the above example, student with id = 1 takes 3 course and is part of 3 clubs.
If i was to find out which courses a student is involved in or which club the student is part of i can do it but i will need to run two queries. Is it possible to run a single query against the
tables listed above so that the results come out like this:
Output
student_id FirstName Student_associated_courses Student_associated_clubs
---------------------------------------------------------------------------
1 Joe 1,2,3 Football, Rugby, Syncronized swimming
3 David 1,3 Tennis
Is it possible to get the above output with just one query? I am using JDBC to get the data so i am trying to see if i can avoid multiple trips to get the necessary data.
use GROUP_CONCAT with DISTINCT in MySQL
SELECT a.student_ID, a.firstname,
GROUP_CONCAT(DISTINCT b.course_ID),
GROUP_CONCAT(DISTINCT c.club_name)
FROM student a
INNER JOIN student_Course b
ON a.student_id = b.student_ID
INNER JOIN student_clubs c
ON a.student_ID = c.student_ID
GROUP BY a.student_ID, a.firstname
See SQLFiddle Demo
Try it like this:
SELECT *
FROM Student s JOIN
(SELECT sc."student_id", listagg(sc."course_id", ',')within group(ORDER BY sc."course_id")
FROM Student_Course sc
GROUP BY sc."student_id") s_course ON s."student_id"=s_course."student_id"
JOIN (SELECT sl."student_id", listagg(sl."club_name", ',')within GROUP(ORDER BY sl."club_name")
FROM Student_clubs sl
GROUP BY sl."student_id") s_club ON s."student_id"=s_club."student_id"
The "catch" is that LISTAGG doesn't work with DISTINCT keyword
Here is a fiddle