SQL JOIN with Team Names from teams table in SQL SERVER - sql

I want to show team name in Match Schedule, I am using below query but it gets me both TeamA & TeamB as same name
SELECT m.ID AS MID, MatchDate,
t.Name AS TeamName, 'v' AS VS,
t.Name AS TeamName, Group
FROM Matches m
JOIN Team T ON m.TeamA_ID = t.Id
JOIN Team T2 ON m.TeamB_ID = t2.Id
How can i get Correct team name based on TeamA_ID, TeamB_ID
Table Team
ID
TeamName
TeamCountry
Table Matches
ID
MatchDate
TeamA_ID
TeamB_ID
Location
Group
ID TeamName TeamCountry
1 TeamOne 100
2 TeamTwo 30
3 TeamThree 80
4 TeamFour 90
5 TeamFive 98
6 TeamSix 99
7 TeamSeven 200
8 TeamEight 14
ID MatchDate TeamA_ID TeamB_ID Location Group
1 01-01-2019 2 4 L1 A
2 02-01-2019 6 1 L1 A
3 04-01-2019 5 8 L1 B
4 06-01-2019 2 6 L1 B
5 10-01-2019 3 4 L1 C
6 16-01-2019 5 6 L1 C
I want result as
ID Date TeamName vs TeamName Location Group
1 01-01-2019 TeamTwo v TeamFour L1 A
2 02-01-2019 TeamSix v TeamOne L1 A
3 04-01-2019 TeamFive v TeamEight L1 B
4 06-01-2019 TeamTwo v TeamSix L1 B
5 10-01-2019 TeamThree v TeamFour L1 C
6 16-01-2019 TeamFive v TeamSix L1 C

Just a simple mistake (you have t.Name twice instead of t2.Name and t.Name)
SELECT m.ID AS MID, MatchDate,
t.Name AS TeamName,
t2.Name AS TeamName,
...

you almost got it.
SELECT m.ID AS MID,
MatchDate,
T.Name AS TeamName,
'v' AS VS,
T2.Name AS TeamName, -- Should be T2.Name
Group
FROM Matches m
JOIN Team T ON m.TeamA_ID = T.Id
JOIN Team T2 ON m.TeamB_ID = T2.Id

In your select you are selecting t.Name twice, change the second one to t2.Name.
SELECT m.ID AS MID, MatchDate,
t.Name AS TeamName, 'v' AS VS,
t2.Name AS TeamName, Group
FROM Matches m
JOIN Team T ON m.TeamA_ID = t.Id
JOIN Team T2 ON m.TeamB_ID = t2.Id

Related

The DATEDIFF function return 2 row

I have the query that works properly and i get the following output :
9 1116 JOHN 0590056093 9106809105 3 A NULL D
9 1117 SARA 0015562451 9203410410 3 A NULL D
9 1118 DAVID 5560101753 9375115360 3 B NULL D
After adding the datediff column my output is as follows
9 1116 JOHN 0590056093 9106809105 3 A NULL D 10
9 1116 JOHN 0590056093 9106809105 3 A NULL D 1
9 1117 SARA 0015562451 9203410410 3 A NULL D 10
9 1117 SARA 0015562451 9203410410 3 A NULL D 1
9 1118 DAVID 5560101753 9375115360 3 B NULL D 10
9 1118 DAVID 5560101753 9375115360 3 B NULL D 1
What is the reason for displaying the 1 in the datediff column?
Query :
select distinct t1.*, fs.Name+' '+ed.Academic as takhasos, Articles.Title, MT.Name as paye,
datediff(m,Projects.StartDateProject, Projects.EndDateProject) as datedif
from
(select RC.ID, RCU.UserID, u.Name + ' ' + u.Family AS NameFamily, u.UserName, u.Mobile, u.Email, groupED.IdMaghtae
from ResearchersCores AS RC LEFT OUTER JOIN
ResearchersCoreUsers AS RCU ON RC.ID = RCU.ResearchersCoreID LEFT OUTER JOIN
Users AS u ON u.Id = RCU.UserID LEFT OUTER JOIN
(SELECT Eductionals.UserID , Max(Eductionals.MaghtaeID) AS IdMaghtae
FROM Eductionals
GROUP BY Eductionals.UserID) groupED
ON u.Id = groupED.UserID
WHERE (RC.IsEnable = 1) AND (RCU.isEnable = 1) AND (RCU.RoleID = 5) ) t1 left outer join
Eductionals as ED ON ED.UserID = t1.UserID AND t1.IdMaghtae = ed.MaghtaeID left outer join
FieldStudies as FS ON ed.FieldStudy_ID = FS.ID left outer join
Articles ON Articles.UserID = t1.UserID left outer join
Projects ON Projects.RecordID = t1.ID and Projects.ControllerID = 8 left outer join
MaghtaeTahsilis MT On MT.ID = t1.IdMaghtae
where t1.id = 9
I want the following output
9 1116 JOHN 0590056093 9106809105 3 A NULL D 10
9 1117 SARA 0015562451 9203410410 3 A NULL D 10
9 1118 DAVID 5560101753 9375115360 3 B NULL D 10
Your query uses distinct to remove duplicate rows. But the expression that you are adding has different values over these otherwise duplicate rows, so they are now showing in the resultset.
One option would be to use group by instead, and take the max() of datediff. This requires you to repeat all other columns in the select clause in the group by clause as well:
select
t1.col1,
t1.col2,
...,
max(datediff(m,Projects.StartDateProject, Projects.EndDateProject)) as datedif
from ...
where t1.id = 9
group by t1.col1, t1.col2, ...

Calculate prior ties individuals have had with other team members prior to current team

I want to calculate the number of prior ties each member has had with other team members prior to the formation of the current team.
I have the following table
TeamId UserId Date
1 100 2/1/2017
1 101 2/1/2017
1 102 2/1/2017
2 100 2//1/2016
2 105 2//1/2016
3 100 2//1/2015
3 101 2//1/2015
3 102 2//1/2015
3 105 2//1/2015
3 106 2//1/2015
4 101 1/3/2015
4 102 1/3/2015
4 105 1/3/2015
4 106 1/3/2015
I want to get the following table
TeamId number of previous collaborations
1 4
2 1
3 6
4 0
For example for team 1:
user 100 has collaborated with user 101 once in team 3 and with user 102 once in team 3therefore = 1+1=2
user 101 has collaborated with user 102 twice (once in team 3 and once in team 4)= 1+1=2
so the number of previous collaborations for this team is 4.
I do not know how to write the code. any help is appreciated
SELECT [TeamId],
COUNT( SELECT [Date] FROM [submissions] s1
WHERE s.[UserId] = [submissions].[UserId]
AND [Date]< [submissions].[Date]
ORDER BY [DateSubmitted] DESC) as Num_Collaborations
)
FROM [submissions]
It's a challenging problem. You have to include the same table 4 times in the query:
select t1.TeamId, t1.UserId, t2.TeamId as OtherTeam, t3.UserId as Collaborator
from #table t1, #table t2, #table t3, #table t4
where t1.UserId = t2.UserId and
t2.TheDate < t1.TheDate and
t3.TeamId = t2.TeamId and
t4.TeamId = t1.TeamId and
t4.UserId = t3.UserId and
t4.UserId < t1.UserId
http://rextester.com/LHZS40204
(then you can group by and count to get the final result)
You can get all the user collaborations with a self-join:
select s.userid, s2.userid as userid2, s.date,
row_number() over (order by (select null)) as c_id
from submissions s join
submissions s2
on s2.teamid = s.teamid;
Let's use this as a subquery to answer your question. The idea is to match the collaborations back to the submissions -- with the constraint that the two users are on the same team at a later date. Then, you can aggregate:
with c as (
select s.userid, s2.userid as userid2, s.date,
row_number() over (order by (select null)) as c_id
from submissions s join
submissions s2
on s2.teamid = s.teamid
)
select s1.teamid, count(distinct c_id) as num_previous_collaborations
from c c join
submissions s1
on s1.userid = c.userid and
s1.date > c.date join -- they are later on a team
submissions s2
on s2.userid = c.userid2 and
s2.teamid = s1.teamid
group by s1.teami;

How to get Oracle to return unique results in a one to many relationship tables with a left join

I have a three tables
Table 1
Id Department
1 A
2 B
3 C
4 D
Table 2
Id DepartId Name
1 1 ABC
2 1 DEF
3 1 ASD
4 2 FGH
5 2 HJK
6 3 ZXC
Table 3
Id Depart Area
1 A pp
2 B
3 C nn
4 D oo
I need the result
Id Depart Name Area
1 A ABC pp
2 B FGH Null
3 C ZXC nn
4 D NULL oo
I need one matching entry from table 2 and table 3 to corresponding entry in the table 1
Do a left join to also get t1 rows without any reference in the t2 table. GROUP BY to get only 1 row per Department.
select t1.id, t1.Department, min(t2.Name)
from t1
left join t2 on t1.id = t2.DepartId
group by t1.id, t1.Department
I think I would do this with a correlated subquery:
select t1.*,
(select t2.name
from t2
where t1.id = t2.DepartId and rownum = 1
) as t2name
from t1;
This saves the overhead of an aggregation. An index on t2(DepartId, name) is optimal for this query.
by the way not the answer to your specific question but if instead of just one you want all the names you can use listagg
SELECT t1.id,
department,
LISTAGG (name, ',') WITHIN GROUP (ORDER BY name) names
FROM t1, t2
WHERE t1.id = t2.departId(+)
GROUP BY t1.id, department
ORDER BY 1
ID Department Names
1 A ABC,ASD,DEF
2 B FGH, HJK
3 C ZXC
4 D

How can I avoiding Cartesian product on SQL on multiple tables

Here is my sqlfiddle http://sqlfiddle.com/#!3/671c8/1.
Here are my tables:
Person
PID LNAME FNAME
1 Bob Joe
2 Smith John
3 Johnson Jake
4 Doe Jane
Table1
PID VALUE
1 3
1 5
1 35
2 10
2 15
3 8
Table2
PID VALUE
1 X1
1 X2
1 X3
2 Z1
3 X3
I am trying to join several tables on a person's ID. These tables contain events with dates, but the dates may or may not match across table. So what I really want it to regardless of date join the tables in a way such that when I get results the table with the largest rows will be the amount of rows in my result and all other tables will "fit" within. For example
Instead of this which is a cartesian product:
PID LNAME FNAME THINGONE THINGTWO
1 Bob Joe 3 X1
1 Bob Joe 3 X2
1 Bob Joe 3 X3
1 Bob Joe 5 X1
1 Bob Joe 5 X2
1 Bob Joe 5 X3
1 Bob Joe 35 X1
1 Bob Joe 35 X2
1 Bob Joe 35 X3
I would like something like this:
PID LNAME FNAME THINGONE THINGTWO
1 Bob Joe 3 X1
1 Bob Joe 5 X2
1 Bob Joe 35 X3
My sql statement:
SELECT
p.*,
t1.value as thingone,
t2.value as thingtwo
FROM
person p
left outer join table1 t1 on p.pid=t1.pid
left outer join table2 t2 on p.pid=t2.pid
;
I can't fathom why you want to do this, but...
You need to create an artificial join between table1 and table2, and then link that to the master table. One way of doing that is by ranking the rows in order. eg:
SELECT
p.pid, p.lname,p.fname, thingone, thingtwo
FROM
person p
left outer join
(
select ISNULL(t1.pid, t2.pid) as pid, t1.value as thingone, t2.value as thingtwo
from
(select *, ROW_NUMBER() over (partition by pid order by value) rn
from table1) t1
full outer join
(select *, ROW_NUMBER() over (partition by pid order by value) rn
from table2) t2
on t1.pid=t2.pid and t1.rn=t2.rn
) v
on p.pid = v.pid
This is a trickier problem than I thought. The challenge is being sure that all the records appear, regardless of the lengths of the two lists. The following works by enumerating each of the lists and using that for the join conditions:
SELECT p.*,
t1.value as thingone,
t2.value as thingtwo
FROM person p left outer join
(select t1.*,
row_number() over (partition by pid order by pid) as seqnum,
count(*) over (partition by pid) as cnt
from table1 t1
) t1
on p.pid = t1.pid left outer join
(select t2.*, row_number() over (partition by pid order by pid) as seqnum,
count(*) over (partition by pid) as cnt
from table2 t2
) t2
on p.pid = t2.pid
WHERE t1.seqnum = t2.seqnum or
(t2.seqnum > t1.cnt) or
(t1.seqnum > t2.cnt) or
t1.seqnum is null or
t2.seqnum is null;
Here is a slight modification to your SQL Fiddle that has better test data.
EDIT:
The logic in the where clause handles these cases (in order by the clauses):
Where the two lists have sequence numbers, these must match.
Where list2 is longer and list1 has at least one element.
Where list1 is longer and list2 has at least one element.
Where list1 is empty
Where list 2 is empty
These were arrived at by trial and error, because the original condition did not work:
on p.pid = t2.pid and t1.seqnum = t2.seqnum
This returns NULL values for p.id for the extra elements on the list. Podliuska's approach may also work; I had just started down this path and the where conditions do the trick.

cross joining two tables

I have a table that looks like this, lets call this table B.
id boardid schoolid subject cnt1 cnt2 cnt3 ....
=================================================================
1 20 21 f
2 20 21 r
3 20 21 w
4 20 21 m
5 20 30 r
6 20 30 w
7 20 30 m
Suppose the counts are just integers. Notice that there is no subject = f for schoolid = 30. Similarly, for most schools, some subject dosnt exist. You might have a schoolid that has just r, w or some that are just r, m, f..
So what I want to do is have 4 consistent rows for each school, and the row that dosnt exist I want dummy values. I thought about creating a secondary table
drop table #A
Select * into #A FROM
(
select [subject_s] = 'r', orderNo = 1
union all
select [subject_s] = 'w', orderNo = 2
union all
select [subject_s] = 'm', orderNo = 3
union all
select [subject_s] = 'f', orderNo = 4
) z
and doing some joins on them, but I've gotten NO where. I've tried inner join, left outer, cross join, everything. I've even tried to make cartesian product. I think my cartesian product messes up because I have orderno in there so it makes 16 rows per row in the main table. Actually typing this out, I realize if I remove the orderno, apply the cartesian product and then add orderno in later, it might work but I am interested to see what you guys can come up with. I am stumped.
End result
id boardid schoolid subject cnt1 cnt2 cnt3 ....
=================================================================
1 20 21 r
2 20 21 w
3 20 21 m
4 20 21 f
5 20 30 r
6 20 30 w
7 20 30 m
7 20 30 f
Try the following:
SELECT S.boardid, S.schoolid, A.[subject], B.cnt1, B.cnt2, B.cnt3
FROM (SELECT DISTINCT boardid, schoolid FROM YourTable) S
CROSS JOIN #A A
LEFT JOIN YourTable B
ON B.boardid = S.boardid AND B.schoolid = S.schoolid
AND A.[subject] = B.[subject]
Since I do not know which RDBMS you are using I tried the following with sqlite and a simpler table:
sqlite> create table schools (name varchar, subject varchar, teacher varchar);
sqlite> select * from schools;
School1|Maths|Mr Smith
School2|English|Jack
School3|English|Jimmy
School3|Maths|Jane
School4|Computer Science|Bob
sqlite> select
schoolnames.name,
subjects.subject,
ifnull(teachers.teacher, "Unknown")
from (select distinct name from schools) schoolnames
join (select distinct subject from schools) subjects
left join schools teachers
on schoolnames.name = teachers.name
and subjects.subject = teachers.subject;
School1|Maths|Mr Smith
School1|English|Unknown
School1|Computer Science|Unknown
School2|Maths|Unknown
School2|English|Jack
School2|Computer Science|Unknown
School3|Maths|Jane
School3|English|Jimmy
School3|Computer Science|Unknown
School4|Maths|Unknown
School4|English|Unknown
School4|Computer Science|Bob
I'd use:
SELECT
boardid, schoolid, dist_subject, id, cnt1, ...
FROM
(SELECT
boardid, schoolid, dist_subject
FROM
(SELECT
DISTINCT subject AS dist_subject
FROM b ) s full outer join
(SELECT
boardid, schoolid
FROM b
GROUP BY
boardid, schoolid ) g ) sg LEFT OUTER JOIN
b ON
sg.boardID = b.boardID AND
sg.schoolid = b.schoolID
sg.dist_subject = b.subject