How can I connect two tables in SQL depending on the data? - sql

It's quite simple problem but I am begginer and i have problems with it.
I have 2 tables in database
matches id, team1id, team2id, score, date
teams id, name
If I want to select team1 name, team2 name, score and date what command should I use?

You should use a double "join" on teams table. I wrote a sheet of how you should use it :
select
matches.id,
teamA.name,
teamB.name,
score,
date
from matches
inner join teams teamA
on teamA.id = matches.team1id
inner join teams teamB
on teamB.id = matches.team2id

Related

How to select players who play multpile game types

I have a SQL table that has "PlayerID" and "GameType" columns. Column "GameType" could be "Video Games" or "Virtual Reality". Some of the players played both of these games and I want to see who is playing both, video games and virtual reality.
I tried to complete this with WHERE and GROUPBY statement, but I keep getting the entire list and not just the players who played both.
Does anyone know the best solution for this problem?
Thank you!!
A common approach is using the HAVING clause which is similar to WHERE, but applies after the GROUP BY.
SELECT PlayerId FROM table
GROUP BY PlayerId
HAVING COUNT(DISTINCT GameType) > 1
If there are more options for GameType than just 'Video Games' and 'Virtual Reality', OwlsSleeping's answer might not work. In this case you can use subqueries as a way to identify which players have played a particular type:
select PlayerID
from mytable
where PlayerID in (
select PlayerID
from mytable
where GameType = 'Video Games')
and PlayerID in (
select PlayerID
from mytable
where GameType = 'Virtual Reality'
)
Alternatively, OwlsSleeping answer can be extended by using a where clause:
SELECT PlayerId FROM table
WHERE GameType in ('Video Games', 'Virtual Reality')
GROUP BY PlayerId
HAVING COUNT(DISTINCT GameType) > 1
What you need to do is create a virtual table by joining your table which has the "PlayerID" and "GameType" columns with the players table. Then you can query the virtual table. Here is an example:
SELECT *
FROM player_game_types
INNER JOIN players
ON player_game_types.PlayerID = players.PlayerID
WHERE player_game_types.GameType = 'Video Games'
INTERSECT
SELECT *
FROM player_game_types
INNER JOIN players
ON player_game_types.PlayerID = players.PlayerID
WHERE player_game_types.GameType = 'Virtual Reality';
Not sure what your table names are, so change player_game_types and players to your actual table names. You can also change the alias if you want.

SQL query for join on different values and aggregation with join

I need to write bunch of queries with a database with the following tables:
Match(homeId, awayId, homeScore, awayScore, date)
League(leagueId, leagueName)
Player(playerId, teamId, playerName, age, position, marketValue, position)
Team(teamId, teamName, leagueId, city)
However, I could not figure out how to write a sql query for the queries like following:
"Find the latest date when Lazio beat Milan in Milan’s home ground."
or
"Find the names of the leagues in which at least one team has at least three
Goalkeepers."
How can I join the Team table with Match table that will give me the matches with team names included. (i.e. homeId, awayId, homeName, awayName) and write these two queries.
Thanks.
For your first requirement, you can use something like this.
select date
from match
where homeid =(select teamid from team where teamname = 'Milan')
and awayId = (select teamid from team where teamname = 'Lazio')
and homeScore < awayScore
For second, use something like below.
select l.leagueName
from league l
inner join Team t
on l.leagueid=t.leagueid
where t.teamid in (
select distinct(teamid) as teamid from player p
where p.position like 'Goalkeeper'
group by teamid
having count(*) >= 3)

Update multiple row values to same row and different columns

I was trying to update table columns from another table.
In person table, there can be multiple contact persons with same inst_id.
I have a firm table, which will have latest 2 contact details from person table.
I am expecting the firm tables as below:
If there is only one contact person, update person1 and email1. If there are 2, update both. If there is 3, discard the 3rd one.
Can someone help me on this?
This should work:
;with cte (rn, id, inst_id, person_name, email) as (
select row_number() over (partition by inst_id order by id) rn, *
from person
)
update f
set
person1 = cte1.person_name,
email1 = cte1.email,
person2 = cte2.person_name,
email2 = cte2.email
from firm f
left join cte cte1 on f.inst_id = cte1.inst_id and cte1.rn = 1
left join cte cte2 on f.inst_id = cte2.inst_id and cte2.rn = 2
The common table expression (cte) used as a source for the update numbers rows in the person table, partitioned by inst_id, and then the update joins the cte twice (for top 1 and top 2).
Sample SQL Fiddle
I think you don't have to bother yourself with this update, if you rethink your database structure. One great advantage of relational databases is, that you don't need to store the same data several times in several tables, but have one single table for one kind of data (like the person's table in your case) and then reference it (by relationships or foreign keys for example).
So what does this mean for your example? I suggest, to create a institution's table where you insert two attributes like contactperson1 and contactperson2: but dont't insert all the contact details (like email and name), just the primary key of the person and make it a foreign key.
So you got a table 'Person', that should look something like this:
ID INSTITUTION_ID NAME EMAIL
1 100 abc abc#inst.com
2 101 efg efg#xym.com
3 101 ijk ijk#fg.com
4 101 rtw rtw#rtw.com
...
And a table "Institution" like:
ID CONTACTPERSON1 CONTACTPERSON2
100 1 NULL
101 2 3
...
If you now want to change the email adress, just update the person's table. You don't need to update the firm's table.
And how do you get your desired "table" with the two contact persons' details? Just make a query:
SELECT i.id, p1.name, p1.email, p2.name, p2.email
FROM institution i LEFT OUTER JOIN person p1 ON (i.contactperson1 = p1.id)
LEFT OUTER JOIN person p2 ON (i.contactperson2 = p2.id)
If you need this query often and access it like a "table" just store it as a view.

Taking Unique Records From Two Tables

i am stuck at a silly problem. And it has to be one of the most cliche solution.
Table student_selection:
Columns
=======
student_id
subject_id
faculty_id
Another table: sub_group
Columns
=======
subject_id
sub_group
They are Joint on subject_id.
I want to find those subject_id from table sub_group where, the subject_id is not present in the student_selection table.
Eg:
sub_group(subject_id)
2
3
4
student_selection(subject_id)
2
3
2
3
2
3
Output
4
You can run a simple not in query to get the data.
Like:
SELECT
subject_id
FROM
sub_group
WHERE
subject_id not in (
SELECT
DISTINCT subject_id
FROM
student_selection
)
Standard SQL IN clause:
select subject_id from sub_group
where subject_id not in (select subject_id from student_selection);
Standard SQL EXISTS clause:
select subject_id from sub_group sg
where not exists
(select * from student_selection ss where ss.subject_id = sg.subject_id);
Set based query. Some dbms support set based operations. They use the word EXCEPT or MINUS to subtract one set from another. (MySQL doesn't support this.)
select subject_id from sub_group
except
select subject_id from student_selection;
At last you can use a trick where you outer join the second table and only stay with those results where there was a record outer-joined (i.e. there is no macthing record in the second table). This is also standard SQL. It is less readable for the unexperienced reader but happens to be faster on some dbms.
select sg.subject_id
from sub_group sg
left join student_selection ss on ss.subject_id = sg.subject_id
where ss.subject_id is null;

How do I join to one row if there are several join matches?

I have 2 tables. I want to join in a way that the latest date is joined for that player. From the below subset, I want the join for Adams to only join to the row with the draw because it was the latest date-wise. How do I go about doing this when you have multiple rows?
ID PLAYER
-------------
2 Adams
3 Rogers
4 David
PLAYER_ID DATE RESULT
------------------------------------
2 01/01/2014 Win
2 01/02/2014 Win
2 01/03/2014 Loss
2 01/04/2014 Draw
I'm assuming player_id and date is a unique combination. Date isn't a good column name. I've assumed your tables names are player and result...in the future, give us table names so answers can include them instead of my guesses.
Building the query:
(select player_ID, max(date) from table group by player_ID)
That will select the maximum date for each player. We are going to use it as a subquery and inner join to it so it acts as a filter. Note that if the player_ID, date combination isn't unique, this will bring back multiple rows per player.
Select player, maxdate
from player p
inner join (select player_ID, max(date) as maxdate from result group by player_ID) a
on a.player_ID = p.player_ID
This will return to you a player and the most recent date. Join that back to the result table to get the result
Select player, result
from player p
inner join (select player_ID, max(date) as maxdate from result group by player_ID) a
on a.player_ID = p.player_ID
inner join result r on r.player_ID = a.player_ID and r.date = a.maxdate
Hopefully that makes sense as to the logic in creating the statement for you.