SQL left join - and after on clause is not working - sql

I have a scenario in left join of SQL which is not generating required output which i need. Following is description in tabular form and my tried queries,
Table A
A_ID // PK OF TABLE A
IS_ACTIVE // VALUE=1 OR 0
Table B
B_ID // PK OF TABLE B
A_ID // FK OF TABLE A IN TABLE B
Sample Records of Table A
A_ID IS_ACTIVE
1 1
2 0
3 1
4 0
5 0
Sample Records of Table B
B_ID A_ID
1 1
2 1
3 4
4 4
5 4
6 4
Select * from A left join B on A.A_ID=B.A_ID
A_ID IS_ACTIVE B_ID A_ID
1 1 1 1
1 1 2 1
2 0 NULL NULL
3 1 NULL NULL
4 0 3 4
4 0 4 4
4 0 5 4
4 0 6 4
5 0 NULL NULL
Select * from A left join B on A.A_ID=B.A_ID and A.IS_ACTIVE=0
Following output is the actual output of above query with no effect to records by adding AND is_active=0 after ON clause.
A_ID IS_ACTIVE B_ID A_ID
1 1 1 1
1 1 2 1
2 0 NULL NULL
3 1 NULL NULL
4 0 3 4
4 0 4 4
4 0 5 4
4 0 6 4
5 0 NULL NULL
Following output is the required output which i need to solve my problem.
A_ID IS_ACTIVE B_ID A_ID
1 1 NULL NULL
1 1 NULL NULL
2 0 NULL NULL
3 1 NULL NULL
4 0 3 4
4 0 4 4
4 0 5 4
4 0 6 4
5 0 NULL NULL
I am facing problem in getting exact records which are required.
I need all records from Table A and matching records from Table B but
those records of Table B which are equal to is_active=0 of Table A.
Note : Query should show all records of Table A
Please help me how can i get this scenario in Left Join of SQL.

I tried your examples as code. And I get the result you needed. What is the problem?
CREATE TABLE #a(a_id int, is_active bit)
CREATE TABLE #b(b_id int, a_id int)
INSERT INTO #a(a_id,is_active)
VALUES(1,1),(2,0),(3,1),(4,0),(5,0)
INSERT INTO #b(b_id,a_id)
VALUES(1,1),(2,1),(3,4),(4,4),(5,4),(6,4)
SELECT *
FROM #a as a
LEFT JOIN #b as b
ON a.a_id = b.a_id
AND a.is_active = 0
DROP TABLE #a
DROP TABLE #b

Have you tried:
Select * from A left join B on A.A_ID=B.A_ID
Where A.IS_ACTIVE=0

Related

SQL Search for missing record, then insert value

Below is a very oversimplified problem I am trying to solve
I have the following tables:
**quiz**
id title
--------------
1 first
2 second
3 third
4 fourth
5 fifth
**quiz_status**
id status user_id quiz_id
-------------------------------
1 0 1 1
2 0 1 2
3 0 1 3
if a I run the following:
select *
from quiz as q
left join quiz_status as qs
ON q.id = qs.quiz_id
where qs.user_id=1
I'd get:
id title id status user_id quiz_id
-------------------------------------------
1 first 1 0 1 1
2 second 2 0 1 2
3 third 3 0 1 3
4 fourth null null null null
5 fifth null null null null
I would like to be able to insert values where missing/null in the quiz_status table.
so the final outcome would be:
id title id status user_id quiz_id
-------------------------------------------
1 first 1 0 1 1
2 second 2 0 1 2
3 third 3 0 1 3
4 fourth 4 0 1 4
5 fifth 5 0 1 5
What would be the insert statement for that?
Consider the insert ... select syntax:
insert into quiz_status(status, user_id, quiz_id)
select 0, u.user_id, q.id
from (select distinct user_id from quiz_status) u
cross join quiz q
left join quiz_status qz on q.id = qz.quiz_id and u.user_id = qz.user_id
where qz.quiz_id is null
This works by generating all combinations of users and quizs, and then left joining the status table to filter on missing records. In the real life, you would likely have a users table that you can use in place of the select distinct subquery.
If you need just one user it's simpler:
insert into quiz_status(status, user_id, quiz_id)
select 0, 1, q.id
from quiz q
left join quiz_status qz on q.id = qz.quiz_id and qz.user_id = 1
where qz.quiz_id is null
Note: presumably, id is a serial column so I left it apart in the inserts.

Sql query null value insertion

Sql Query
SELECT respondant.respondant_firstname as first_name,
question.question_id as question_id,
answer.answer_id,
answer.answer_text,
answer.answer_rate,
answer.answer_nps,
question_radio.question_radio_text as opt
FROM question
LEFT JOIN answer on answer.answer_question_id = question.question_id
LEFT JOIN question_radio on answer.answer_question_radio_id = question_radio.question_radio_id
LEFT JOIN respondant on answer.answer_respondant_id = respondant.respondant_id
WHERE question.question_feedback_id = 1
ORDER BY question.question_id, answer.answer_id
Output:
first_name question_id answer_id answer_text answer_rate answer_nps opt
RM 1 1 5 NULL NULL
Y 1 3 0 NULL NULL
Ben 1 5 0 NULL NULL
akash 1 8 2.5 NULL NULL
RM 2 2 0 4 NULL
Y 2 4 0 3 NULL
Ben 2 6 0 0 NULL
akash 2 9 0 0 NULL
Ben 3 7 Thanks 0 0 NULL
akash 3 10 0 0 NULL
I Need the output as:
first_name question_id answer_id answer_text answer_rate answer_nps opt
RM 1 1 5 NULL NULL
Y 1 3 0 NULL NULL
Ben 1 5 0 NULL NULL
akash 1 8 2.5 NULL NULL
RM 2 2 0 4 NULL
Y 2 4 0 3 NULL
Ben 2 6 0 0 NULL
akash 2 9 0 0 NULL
RM 3 NULL 0 0 NULL
Y 3 NULL 0 0 NULL
Ben 3 NULL ThankS 0 0 NULL
akash 3 NULL 0 0 NULL
Where in third and fourth row from last doesnt have the id 3 but i need to replace as 3 and other values in that two rows has to be null
What you want to do is rather complicated. You want a row for each responder and question, and then to fill in the details for those that responded. My guess is that you want the answer_id filled in, where available. That is, your desired results should have answer_ids for "Ben" and "Akash".
The following query generates all the rows using a cross join between the responders and the questions. Then it brings in the additional information:
SELECT r.respondant_firstname as first_name, q.question_id as question_id,
a.answer_id, a.answer_text, a.answer_rate, a.answer_nps,
qr.question_radio_text as opt
FROM respondant r CROSS JOIN
question q LEFT JOIN
answer a
on a.answer_question_id = q.question_id and
a.answer_respondant_id = r.respondant_id LEFT JOIN
question_radio qr
on a.answer_question_radio_id = qr.question_radio_id
WHERE q.question_feedback_id = 1
ORDER BY q.question_id, a.answer_id;

PLSQL UPDATE BASED ON ROWS FROM OTHER TABLE

I have following tables in APEX A and B.
A has columns:
ID_A;
VALUE;
B has columns:
ID_C_FK;
ID_A_FK
I want to update the VALUE column in table A in rows where ID_A equals ID_A_FK in selected rows from table B where ID_C_FK equal x
For example: A has rows (
ID_A value
------------
1 1
2 1
3 0
4 0
5 0
Table B has rows
ID_C_FK ID_A_FK
------------------
8 4
9 4
9 5
I want to update VALUE in table A only for those rows that have ID_A in rows selected from B and condition to select rows from B is that ID_C_FK equals x = 9; and as a result, table A should end up having rows:
ID_A value
------------
1 1
2 1
3 0
4 1
5 1
How to write such update in PL/SQL?
Thank you for considering my request.
I think this is what you want:
update a
set value = 1
where exists (select 1
from b
where b.id_a_fk = a.id_a and b.id_c_fk = 9
);

Selecting rows and filler (null data)

I have a table that looks like this:
ReportID | TeamID | Inning | Runs
1 A 1 3
1 A 2 3
1 A 5 7
1 B 1 3
1 B 3 2
1 B 6 1
I need to select all of that data, plus null data for the missing innings. It also need to stop at the max Inning for both teams (i.e. teamB's highest inning is 6, so I would collect 6 rows for both teamA and teamB yielding 12 total rows.)
For a visual, I need the output of the query to look like this:
ReportID | TeamID | Inning | Runs
1 A 1 3
1 A 2 3
1 A 3 NULL
1 A 4 NULL
1 A 5 7
1 A 6 NULL
1 B 1 3
1 B 2 NULL
1 B 3 2
1 B 4 NULL
1 B 5 NULL
1 B 6 1
Is there anyway to do this with just a query? Modifying the original table to add the null values is not an option.
Self join to generate the permutations of reports and teams
Left self join to generate hits which might be nullable.
This is probably a lot more efficient if it's done outside of SQL
SELECT ins.ReportID, teams.TeamID, ins.inning, score.Runs
FROM games as ins
JOIN games AS teams
ON ins.ReportID = teams.ReportID
LEFT JOIN games AS score
ON ins.ReportID = score.ReportID
AND teams.TeamID = score.TeamID
AND ins.inning = score.inning
GROUP BY ins.ReportID, teams.TeamID, ins.inning;

How to update one table based on aggregate query form another table

Say I have two tables.
Table A
id
A_status
parent_id_B
Table B
id
B_status
So for each id in B can have many records in A.
Now my question is, I need to set B_status to 1 when all child entries in Table A with same parent_id_B has A_status =1, else set B_status = 2
Ex:
Table A:
id A_status parent_id_B
1 1 1
2 1 1
3 1 2
4 1 3
5 1 3
Table B:
id B_status
1 0
2 0
3 0
Expected result:
Table B:
id B_status
1 1
2 1
3 1
Now consider another scenario
Table A:
id A_status parent_id_B
1 1 1
2 1 1
3 2 2
4 2 3
5 1 3
Table B:
id B_status
1 0
2 0
3 0
Expected result:
Table B:
id B_status
1 1
2 2
3 2
I need this to work only on sqlite. Thanks
I believe this can be done like so:
UPDATE TableB
SET B_Status =
(SELECT MAX(A_Status) FROM TableA WHERE TableA.Parent_ID_B = TableB.ID);
SqlFiddle with your second case here
In a more general case (without relying on direct mapping of A's status, you can also use a CASE ... WHEN in the mapping:
UPDATE TableB
SET B_Status =
CASE WHEN (SELECT MAX(A_Status)
FROM TableA
WHERE TableA.Parent_ID_B = TableB.ID) = 1
THEN 1
ELSE 2
END;
Edit (in the case where there are more than the original number of states):
I believe you'll need to determine 2 facts about each row, e.g.
Whether there is are any rows in table A with a status other than 1 for each B
And there must at least be one row for the same B
Or, whether the count of rows of A in state 1 = the count of all rows in A for the B.
Here's the first option:
UPDATE TableB
SET B_Status =
CASE WHEN
EXISTS
(SELECT 1
FROM TableA
WHERE TableA.Parent_ID_B = TableB.ID
AND TableA.A_Status <> 1)
OR NOT EXISTS(SELECT 1
FROM TableA
WHERE TableA.Parent_ID_B = TableB.ID)
THEN 2
ELSE 1
END;
Updated Fiddle