How to select all values between 2 tables in SQL? - sql

I have the following two tables in Oracle database (read only access so I can only use select).
Question table:
N Question ID
1 1
2 2
3 3
Response table:
Question ID Response day
1 01-04-15
3 02-04-15
4 03-04-15
I want the output result to be:
Question ID Response day
1 01-04-15
2 null
3 02-04-15
4 03-04-15
I m strying with the following query and I'm ony getting the question ID when there is a response. Anyone know where I'm going wrong?
select questionID, responseday
from questions
join response
where question.question.ID = response.question.ID;
With this query I'm getting these results:
Question ID Response day
1 01-04-15
3 02-04-15
4 03-04-15

One method is a full outer join:
select coalesce(q.questionid, r.questionid) as questionid,
r.responseday
from questions q full outer join
responses r
on q.questionid = r.questionid;

Based on your schema, a simple LEFT JOIN will be sufficient for your model.
SELECT q.Question_ID,
r.Response_Day
FROM Question AS "q"
LEFT JOIN Response AS "r"
ON r.Question_ID = q.Question_ID;
JOIN or INNER JOIN will only return the result sets from both tables where ALL attributes match. Because your Question record with ID of 2 does not exist in the Response table, SQL will exclude this data.
To account for NULLs, you have to LEFT JOIN, see the sqlfiddle here:
SQL Fiddle
Also, have a look at this graphical model explaining all the JOINs:
Visual Representation of SQL Joins

Use Left Join
select
q.questionid as questionid,
r.responseday
from
questions q
left join
responses r
on
q.questionid = r.questionid;

FULL outer JOIN is sufficient or the output required.
SELECT NVL(a.id,b.id),
b.nm
FROM
(SELECT 1 id,1 nm FROM dual
UNION ALL
SELECT 2 id,2 nm FROM dual
UNION ALL
SELECT 3 id,3 nm FROM dual
)a
FULL OUTER JOIN
(SELECT 1 id,'01-04-15' nm FROM dual
UNION
SELECT 3 id,'02-04-15' nm FROM dual
UNION ALL
SELECT 4 id,'03-04-15' nm FROM dual
)b
ON a.id = b.id;
---------------------------------OUTPUT -----------------------------------
ID NM
1 01-04-15
3 02-04-15
4 03-04-15
2 NULL
----------------------------------OUTPUT-----------------------------------

select questionID
, responseday
from questions
join response
on question.question.ID = response.question.ID;

Related

Join two child records next to each other in one row in PL Sql [duplicate]

This question already has an answer here:
Join/Pivot items with EAV table
(1 answer)
Closed 1 year ago.
I have 2 tables,
select * from Srn_Table1;
ID
CUSTOMERNAME
1
TEST CUSTOMER
select * from Srn_Table2;
ID
ADDRESS
ADDRESSID
1
palakkad
1
1
thrissur
2
I need the Result as
ID
ADDRESS
ADDRESSID
ADDRESS
ADDRESSID
1
palakkad
1
thrissur
2
ID is common.
How can I join the 2 tables to get the result..?
I would add a row number to the second table, so that you can join that table once for when that row number is 1, and a second time for when it is 2:
with ext as (
select Srn_Tablea2.*,
row_number() over (partition by id order by addressid) rn
from Srn_Tablea2
)
select a.id, b.address, b.addressid, c.address, c.addressid
from Srn_Tablea1 a
left join ext b on a.id = b.id and b.rn = 1
left join ext c on a.id = c.id and c.rn = 2;
Of course, if you have cases where you have 3 or more addresses for the same id, you'll have to create more joins, and produce more columns. But the principle remains the same.

SQL Query: Count "id" occurrences in two tables

I have these 3 tables and I am trying to count, how many "hints" and "quizzes" are there for specific town id.
db_town
id
town
1
New York
db_hint
id
town_id
hint
1
1
test
db_quiz
id
town_id
quiz
1
1
quiz 1
2
1
quiz 2
I am using this statement, but it does not work :(
SELECT count(q.id),count(h.id) FROM `db_town` t LEFT JOIN `db_quiz` q ON t.id = q.town_id LEFT JOIN `db_hint` h ON t.id = h.town_id WHERE t.id = 1 GROUP BY t.id
and it produces this result:
count(q.id)
count(h.id)
2
2
Do I need to use two statements? Or is it possible to query it in a single SQL statement? I am using MariaDB.
You can use union all and aggregation:
select town_id, sum(is_hint), sum(is_quiz)
from ((select town_id, 1 as is_hint, 0 as is_quiz
from hints
) union all
(select town_id, 0, 1
from quizzes
)
) t
group by town_id;
Alternatively, you can use correlated subqueries:
select t.*,
(select count(*) from hints h where h.town_id = t.id),
(select count(*) from quizzes q where q.town_id = t.id)
from towns t;
Two things to look out for:
JOINs are likely to multiply rows and throw off the counts.
Getting 0 values if a town has no hints or quizzes.
You can use COUNT (DISTINCT) if both the hint id and the quiz id are unique.
SELECT
count(distinct q.id),count(distinct h.id)
FROM `db_town` t
LEFT JOIN `db_quiz` q ON t.id = q.town_id
LEFT JOIN `db_hint` h ON t.id = h.town_id
WHERE t.id = 1 GROUP BY t.id

Is it possible to replace content from multiple foreign keys when doing a query?

I have the following tables:
TABLE PLAYER
id | name
1 | A
2 | B
3 | C
4 | D
TABLE PAIRINGS
id | player_a | player_b
1 | 3 |1
2 | 2 |4
Both columns in table Pairings are foreign keys to column id of table player.
My problem is, I would like to avoid making a query from code every time I want to know which is my player's name (like, Select name From Player Where Id = pairings.player_a). I have thought about adding Name as an extra columnd to Pairings table, but that would denormalize it.
Instead, it would be nice if I could get the names in just one query, like:
RESULT
player_a | player_b
C | A
B | D
Is it this possible? Thanks so much in advance.
You may join the PAIRINGS table to the PLAYER table, twice:
SELECT
p1.name AS player_a,
p2.name AS player_b
FROM PAIRINGS pr
INNER JOIN PLAYER p1
ON pr.player_a = p1.id
INNER JOIN PLAYER p2
ON pr.player_b = p2.id;
Demo
Don't do it! One of the points of using a relational database is that data is stored in only one place. That is a big convenience. Of course, there are exceptions, but these exceptions should have firm reasons.
In this case, just define a view:
CREATE VIEW vw_pairings AS
SELECT p.*, pa.name AS player_a_name,
pb.name AS player_b_name
FROM PAIRINGS p JOIN
PLAYER pa
ON p.player_a = pa.id JOIN
PLAYER pb
ON p.player_b = pb.id;
When you query from the view, you will see the names, along with all the other information in the PAIRINGS table.
Hope can help you
Select * Into #PLAYER From (
Select 1 [ID], 'A' [Name] Union All
Select 2 [ID], 'B' [Name] Union All
Select 3 [ID], 'C' [Name] Union All
Select 4 [ID], 'D' [Name]
) A
Select * Into #PAIRINGS From (
Select 1 [ID], 3 [PLAYER_A], 1 [PLAYER_B] Union All
Select 2 [ID], 2 [PLAYER_A], 4 [PLAYER_B]
) A
Select
P.ID, A.NAME, B.NAME
From #PAIRINGS P
Left Join #PLAYER A On A.ID = P.PLAYER_A
Left Join #PLAYER B On B.ID = P.PLAYER_B
You can create view, for avoid making query
Example
Create View vwPAIRINGS As
Select
P.ID, A.NAME, B.NAME
From #PAIRINGS P
Left Join #PLAYER A On A.ID = P.PLAYER_A
Left Join #PLAYER B On B.ID = P.PLAYER_B
After that, just select usual
Select * from vwPAIRINGS

Pivot Creates an extra Row for Null values of Pivot Key

I am using oracle sql developer and trying to pivot in based on IssueId and expecting to get one row. But it creates an extra row for null values of issue but I want all values in one row. Please, see below scenario for better explanation of this confusing problem.
Table I have after joins :
Data:
Current Result with Extra Null Row:
Expected Result:
My Query:
select *
from
(
select TableB.SEQ_ID,TableA.ISSUEID , TableC.Question
from TableC RIGHT JOIN TableB ON TableC.QUESTIONID = TableB.QUESTION_ID
LEFT JOIN TableA ON TableB.QUESTION_ID = TableA.QUESTIONID AND ISSUEID = 3250
) d
pivot
(
MAX(Question)
for SEQ_ID in ( 1, 2, 3 ,4, 5 )
) piv;
Any suggestions related to this is appreciated. Thank You!
Assuming the intermediate result set is what you expect to see and the left/right outer joins are necessary for what you're trying to do, you could just replace the null issue IDs from rows not matching in table A, using an analytic aggregate:
max(TableA.ISSUEID) over () as ISSUEID
With sample data that gets the same intermediate result you showed, the modified inner query:
select TableB.SEQ_ID, max(TableA.ISSUEID) over () as ISSUEID, TableC.Question
from TableC
RIGHT JOIN TableB ON TableC.QUESTIONID = TableB.QUESTION_ID
LEFT JOIN TableA ON TableB.QUESTION_ID = TableA.QUESTIONID AND TableA.ISSUEID = 3250;
gets
SEQ_ID ISSUEID QUESTION
---------- ---------- -------------
1 3250 How are You?
2 3250 Hows it going
3 3250 Is It Okay?
4 3250 Whats Up?
5 3250 Really?
and when pivoted:
select *
from
(
select TableB.SEQ_ID, max(TableA.ISSUEID) over () as ISSUEID, TableC.Question
from TableC
RIGHT JOIN TableB ON TableC.QUESTIONID = TableB.QUESTION_ID
LEFT JOIN TableA ON TableB.QUESTION_ID = TableA.QUESTIONID AND TableA.ISSUEID = 3250
) d
pivot
(
MAX(Question)
for SEQ_ID in ( 1, 2, 3 ,4, 5 )
) piv;
gets
ISSUEID 1 2 3 4 5
---------- ------------- ------------- ------------- ------------- -------------
3250 How are You? Hows it going Is It Okay? Whats Up? Really?
You could get the same result with:
select * from (
select b.seq_id, a.issueid, c.question
from tableb b
join tablec c on c.questionid = b.question_id
cross join (
select issueid from tablea where issueid = 3250
) a
) d
pivot
(
max(question)
for seq_id in (1, 2, 3 ,4, 5)
);
(or cross apply in 12c+), which also works with condition >= 3250. This just lists all five questions against every matching issue ID. That may not actually be what you want to do, but it's what your very limited sample data and expected results suggest.
If you only want valid issues, then don't mess around with all those outer joins. Just start with the table that has the rows you want to keep, us left join for the other tables, and filter the first table in the where clause:
from (select TableB.SEQ_ID, TableA.ISSUEID , TableC.Question
from TableA LEFT JOIN
TableB
on TableB.QUESTION_ID = TableA.QUESTIONID LEFT JOIN
TableC
on TableC.QUESTIONID = TableB.QUESTION_ID
where tableA.ISSUEID = 3250
) d

Table Join Distinct Field

The problem which I am having is joining two tables. One table contains all the generic data and the second table contains old fields which have been given specific values. The exemplary tables below should help to clarify my setup.
Table 1 (Generic Data)
ParaIndex ParaName ParaDefault
1 Cat 15
2 Fish 8
3 Dog 3
Table 2 (Specific Data)
Project ParaIndex ParaValue
John 1 6
John 2 7
Alan 3 9
The goal then is to join these tables to get a single table:
Table 3 (Table Join on ParaIndex for 'John')
ParaName ParaIndex ParaValue ParaDefault
Cat 1 6 15
Fish 2 7 8
Dog 3 3
So Table 3 would return all rows from Table 1 but would only show values for ParaValue where they are not empty. E What I have tried so far is a combination of changing the join type, distinct select, group by, select subqueries, and suggestions mentioned in other posts.
The end goal is then to use this query in vb.net as par of a form.
The closest which I have gotten is to return the requested data in table 3, but it would exclude rows which are not requested (e.g. if the query is for 'John' it would then exclude the parameters marked by 'Alan' which is 3-Dog in this case).
SELECT t1.ParaName, t1.ParaIndex, t2.ParaValue, t1.ParaDefault
FROM Table1 AS t1LEFT OUTER JOIN Table2 AS t2
ON t1.ParaIndex = t2.ParaIndex
WHERE (((t2.ParaIndex) is null) OR t2.Project = 'John')
You have to use a LEFT OUTER JOIN:
SELECT t1.ParaName,
t1.ParaIndex,
COALESCE(CAST(t2.ParaValue AS VARCHAR(10), '') AS ParaValue,
t1.ParaDefaule,
FROM dbo.Table1 t1
LEFT OUTER JOIN dbo.Table2 t2
ON t1.ParaIndex = t2.ParaIndex
WHERE t2.Project = 'John'
ORDER BY t1.ParaIndex