Oracle SQL select from multiple tables - sql

Oracle SQL select from multiple tables and join them. Looking to find the players Full Name, Email Address, Player Number, COUNTRY_ID who are from Australia where the player type = NEW OR EXE
SELECT T.FIRST_NAME, T.LAST_NAME, E.EMAIL_ID, PN.PLAYER, C.COUNTRY_ID
FROM PLAYER_TYPE T
LEFT JOIN PLAYER_CONTACT C
ON T.PLAYER_ID = C.PLAYER_ID
RIGHT JOIN PLAYER_CONTACT C
ON P.CONTACT_ID = C.CONTACT_ID
AND C.COUNTRY_CODE='AUS'
AND T.PLAYER_TYPE = 'NEW' OR 'EXE'
Below is the expected output
MARK CLARKSON dfgh#gmail.com 480 04
CATH SPEARS tygh#yahoo.com 481 04
FESS LOPEZ fgvhb#yandex.com 482 04
FEXS LOPEZ byvg#google.com 483 04
EOVA SMITH ghjkjh#sdf.com 493 04
Here is the SQL fiddle
https://dbfiddle.uk/LPzlOcwB

T.PLAYER_TYPE = 'NEW' OR 'EXE' is not valid syntax and you can use INNER JOIN rather then an OUTER JOIN and need to join all the tables rather than joining player_contact twice.
Like this:
SELECT t.first_name || ' ' || t.last_name AS full_name,
e.email_id,
p.player_number,
p.country_id
FROM playertype t
INNER JOIN player p
ON (p.player_id = t.player_id)
INNER JOIN country_table c
ON (p.country_id = c.country_id)
INNER JOIN player_contact pc
ON (p.player_id = pc.player_id)
INNER JOIN contact_email e
ON (pc.contact_id = e.contact_id)
WHERE player_type IN ('NEW', 'EXE')
AND c.country_name = 'AUSTRALIA'
Which, for your sample data, outputs:
FULL_NAME
EMAIL_ID
PLAYER_NUMBER
COUNTRY_ID
MARK CLARKSON
dfgh#gmail.com
480
04
CATH SPEARS
tygh#yahoo.com
481
04
FESS LOPEZ
fgvhb#yandex.com
482
04
FEXS LOPEZ
byvg#google.com
483
04
EOVA SMITH
ghjkjh#sdf.com
493
04
fiddle

Related

Moodle - configurable reports query scorm?

i hope someone can help me :)
I need a query to get user name | scorm module name | module start date | module completition date | (optional) total_time
My query for now is this but i'm not so good with postgresql :(
SELECT
u.firstname AS First,
u.lastname AS Last,
sc.name AS Modulo,
st.value AS Status,
'' AS Inizio,
TO_CHAR(TO_TIMESTAMP(st.timemodified), 'DD/MM/YYYY HH24:MI') AS Completamento
FROM prefix_scorm_scoes_track AS st
JOIN prefix_user AS u ON st.userid=u.id
JOIN prefix_user_info_data AS uid ON uid.userid = u.id
JOIN prefix_scorm AS sc ON sc.id=st.scormid
JOIN prefix_course AS c ON c.id=sc.course
JOIN prefix_groups AS g ON g.courseid = c.id
JOIN prefix_groups_members AS m ON g.id = m.groupid
WHERE (st.element='cmi.core.lesson_status' and st.value = 'completed') AND m.userid=u.id and c.id = %%COURSEID%%
UNION
SELECT
user2.firstname AS First,
user2.lastname AS Last,
'' AS Modulo,
'not_started' AS status,
TO_CHAR(TO_TIMESTAMP(st.value::int), 'DD/MM/YYYY HH24:MI') AS Inizio,
CAST(NULL AS text) AS Completamento
FROM prefix_user_enrolments AS ue
JOIN prefix_enrol AS e ON e.id = ue.enrolid
JOIN prefix_course AS c ON c.id = e.courseid
JOIN prefix_user AS user2 ON user2 .id = ue.userid
JOIN prefix_user_info_data AS uid ON uid.userid = user2.id
JOIN prefix_groups AS g ON g.courseid = c.id
JOIN prefix_groups_members AS m ON g.id = m.groupid
JOIN prefix_scorm AS sc ON sc.course=c.id
Left Join prefix_scorm_scoes_track AS st on st.scormid=sc.id AND st.userid=user2.id
WHERE st.element = 'x.start.time' AND m.userid=user2.id and c.id = %%COURSEID%%
ORDER BY Last, First
The output is this:
first last modulo status inizio completamento
name lastname module 1 completed 29/03/2021 16:57
name lastname module 1 not_started 29/03/2021 16:52
name lastname module 2 not_started 31/03/2021 11:37
name lastname module 2 completed 31/03/2021 11:41
name lastname module 3 not_started 31/03/2021 11:26
name lastname module 3 completed 31/03/2021 11:32
name lastname module 4 not_started 31/03/2021 11:52
name lastname module 4 completed 31/03/2021 12:10
So now my question is how can i combine the results to have "inizio" and "completamento" on the same row?

easiest way to substract in one column and add in other

Basically I'm trying to move existances from one register to another, substracting from the origin point and adding it to the destiny. I have one table of "Stocks" like this:
country city value
AA 01 500
AA 02 400
BB 01 300
CC 01 100
CC 02 1000
CC 03 2000
And I am receiving a document of "movements" with a structure like this:
quantity originCountry originCity endCountry endCity
10 AA 01 CC 01
20 AA 01 BB 02
50 BB 01 CC 03
Is there a way to do this without creating two normalized tables and several queries.
Edit
The answer must be like this:
quantity originCountry originCity endCountry endCity
AA 01 470
AA 02 400
BB 01 250
CC 01 110
CC 02 1020
CC 03 2050
negative number and business rules aren't relevant
try this (isnull is for tsql):
SELECT country, city, value - isnull(p, 0) + isnull(m, 0) as q
FROM Stocks AS s
LEFT JOIN (SELECT originCountry, originCity, Sum(quantity) m FROM movements GROUP BY originCountry, originCity) AS mm
ON originCountry = s.country AND originCity = s.city
LEFT JOIN (SELECT endCountry, endCity, Sum(quantity) p FROM movements GROUP BY endCountry, endCity) AS mp ON
ON endCountry = s.country AND endCity = s.city
For MS ACCESS (add tag next time...):
this should by work:
SELECT country, city, value - Nz(p, 0) + Nz(m, 0) as q
FROM ((Stocks AS s
LEFT JOIN (SELECT originCountry, originCity, Sum(quantity) m FROM movements GROUP BY originCountry, originCity) AS mm
ON (originCountry = s.country AND originCity = s.city))
LEFT JOIN (SELECT endCountry, endCity, Sum(quantity) p FROM movements GROUP BY endCountry, endCity) AS mp ON
ON (endCountry = s.country AND endCity = s.city))
or this ((if you get error then use DSum function):
SELECT country, city, value
- Nz((
SELECT Sum(quantity) m
FROM movements
WHERE originCountry = s.country AND originCity = s.city
), 0) + Nz((
SELECT Sum(quantity) p
FROM movements
WHERE endCountry = s.country AND endCity = s.city
), 0) as q
FROM Stocks AS s

Iterate Data Table ontop of another Data table and make one table

I have a question.
Here is the story, I have Student mark sheet (Table A)
Name Course Marks
Student 01 32472 44
Student 02 32472 80
Student 03 32472 67
Student 04 32472 76
Student 05 32472 56
Student 06 32472 98
Student 07 32472 13
Student 08 32472 68
Student 09 32472 84
Student 10 32472 93
And I have sheet (Table B ) for cut off marks for medals.
Medel Course CutOff
Silver 32472 0-69
Gold 32472 70 -84
Platinum 32472 85 -100
Could you please help me to get following sheet (Table) in SQL.
Name Course Medal
Student 01 32472 Silver
Student 02 32472 Gold
Student 03 32472 Silver
Student 04 32472 Gold
Student 05 32472 Silver
Student 06 32472 Platinum
Student 07 32472 Silver
Student 08 32472 Silver
Student 09 32472 Gold
Student 10 32472 Platinum
How Can I join Table A (Student marks sheet) and Table B (Medal cut off marks sheet) then get Final Table ?
Really appreciate your answers/comments.
Thank you
Gayan
After your edit:
;WITH CteMedals AS(
SELECT *,
rStart = LEFT(CutOff, CHARINDEX('-', CutOff) - 1),
rEnd = SUBSTRING(CutOff, CHARINDEX('-', CutOff) + 1, LEN(CutOff) - CHARINDEX('-', CutOff))
FROM TableB
)
SELECT
a.Name, a.Course, ISNULL(b.Medal, 'Silver') AS Medal
FROM TableA a
OUTER APPLY(
SELECT TOP 1 Medal
FROM CteMedals
WHERE
a.Marks BETWEEN rStart AND rEnd
ORDER BY rEnd DESC
)b
You can use OUTER APPLY:
SELECT
a.Name, a.Course, ISNULL(b.Medal, 'Silver') AS Medal
FROM TableA a
OUTER APPLY(
SELECT TOP 1 Medal
FROM TableB
WHERE
a.Marks >= CutOff
ORDER BY CutOff DESC
)b

SQL finding distinct pairs

I'm trying to figure out how to write an SQL query to find the distinct pairs of student ids that have the same quarter and year and class id and that have been in more than one classid together.
So the database looks like this
Studentid courseid quarter year
11035 1020 Fall 2012
11035 1092 Fall 2012
75234 3201 Winter 2012
8871 1092 Fall 2013
39077 1092 Fall 2013
57923 9219 Winter 2013
60973 9219 Winter 2013
19992 3201 Winter 2013
60973 8772 Spring 2013
90421 8772 Spring 2013
90421 2987 Spring 2013
60973 2987 Spring 2013
the result that I am trying to get is:
Studentid student id year quarter course id
60973 90421 2013 Spring 8772
60973 90421 2013 Spring 2987
so far I have
SELECT s.studentid,
st.studentid,
st.year,
s.quarter,
st.courseid
FROM enrolled s
LEFT JOIN enrolled st
ON st.COURSEID = s.COURSEID
WHERE s.QUARTER = st.quarter
AND s.YEAR = st.year
AND s.studentid <> st.studentid
but it is giving me every combination that can be created
Self join twice - once for the match, and again for to find a different match:
SELECT s.studentid, st.studentid, s.year, s.quarter, s.courseid
FROM enrolled s
JOIN enrolled st ON st.COURSEID = s.COURSEID
AND st.quarter = s.quarter
AND st.year = s.year
AND s.studentid < st.studentid
JOIN enrolled e2 ON e2.COURSEID != s.COURSEID
AND e2.quarter = s.quarter
AND e2.year = s.year
AND e2.studentid = st.studentid
Output:
| STUDENTID | OTHER_STUDENTID | YEAR | QUARTER | COURSEID |
|-----------|-----------------|------|---------|----------|
| 60973 | 90421 | 2013 | Spring | 2987 |
| 60973 | 90421 | 2013 | Spring | 8772 |
See SQLFiddle
Notes:
You want an (inner) join, not a left join
Use s.studentid < st.studentid to stop:
students joining to themselves, and
both sides of pairs from displaying
Use a different course for the second join but the same other student id
SELECT a.*,b.courseid
FROM (SELECT a.year
,a.quarter
,a.studentid AS Student1
,b.studentid AS Student2
FROM enrolled a
JOIN enrolled b
ON a.COURSEID = b.COURSEID
AND a.QUARTER = b.quarter
AND a.YEAR = b.year
AND a.courseid = b.courseid
AND a.studentid < b.studentid
GROUP BY a.year,
a.quarter,
a.studentid,
b.studentid
HAVING COUNT(*) > 1) a
JOIN enrolled b
ON a.year = b.year
AND a.quarter = b.quarter
AND a.Student1 = b.studentid
SQL Fiddle
I added a row in the table: (11035, 2987, 'Spring', 2013) That row breaks some answers that work with your sample data. You need a HAVING clause to ensure the pair of students have more than 1 class together in a given quarter.
Using a CTE for the aggregate:
WITH pairs AS (
SELECT distinct e1.Studentid AS student1
, e2.Studentid AS student2
FROM enrolled e1
JOIN enrolled e2 ON e1.courseid = e2.courseid AND e1.quarter = e2.quarter AND e1.year = e2.year
WHERE e1.Studentid < e2.Studentid
GROUP BY e1.Studentid,e2.Studentid
HAVING COUNT(*) > 1
)
SELECT e1.Studentid AS student1
, e2.Studentid AS student2
, e1.courseid
, e1.quarter
, e1.year
FROM pairs p
JOIN enrolled e1 ON e1.Studentid = p.student1
JOIN enrolled e2 ON e2.Studentid = p.student2
WHERE e1.courseid = e2.courseid AND e1.quarter = e2.quarter AND e1.year = e2.year
;

How to combine two tables with vary columns and vary relations in SQL

How do I combine columns and rows in the following example in SQL without pulling extra rows with nulls on columns that not existing in the other table? This should be similar to the OUTER UNION CORR in SAS.
EMP_ID and Dept_ID in the two tables don't have the exact ID list, e.g. ID in table A might not be in table B so as the other way around.
Table A
EMP_ID Dept_ID VISIT_CA_DATE
001 01 5/2/2011
002 02 null
004 03 6/8/2011
Table B
EMP_ID Dept_ID LAST_OUT REASON
001 01 6/1/2011 sick
003 02 7/2/2011 vacation
Expecting result like this - all EMP_ID with corresponding visit_date info and absent info.
EMP_ID Dept_ID VISIT_CA_DATE LAST_OUT REASON
001 01 5/2/2011 6/1/2011 sick
002 02 null null null
003 02 null 7/2/2011 vacation
004 03 6/8/2011 null null
The only way worked for me is below. Is there better way to achieve this? Thanks!
A LEFT OUTER JOIN B on A.EMP_ID=B.EMP_ID
UNION
B LEFT OUTER JOIN A ON B.EMP_ID=A.EMP_ID
You can do a FULL OUTER JOIN. It's basically a LEFT JOIN and a RIGHT JOIN combined. Something like this:
SELECT COALESCE(A.Emp_Id,B.Emp_Id) Emp_Id,
COALESCE(A.Dept_Id,B.Dept_Id) Dept_Id,
A.VISIT_CA_DATE,
B.LAST_OUT,
B.REASON
FROM TableA A
FULL OUTER JOIN TableB B
ON A.Emp_Id = B.Emp_Id AND A.Dept_Id= B.Dept_Id
SELECT t.EMP_ID, t.Dept_Id, A.VISIT_CA_DATE, B.LAST_OUT, B.REASON
FROM (
SELECT EMP_ID, Dept_Id FROM A
UNION
SELECT EMP_ID, Dept_Id FROM B
) t
LEFT JOIN A ON t.EMP_ID = A.EMP_ID
LEFT JOIN B ON t.EMP_ID = B.EMP_ID
Altough It probably it looks like about the same as you did.