Joining conditionally based on values in 2 different columns in current table - sql

SELECT
l.*,
qqs.*,
qq.*,
-- cqqs.id As Cosigner_Quote_Set_ID,
-- borrower_cosigner_quote_set_uuid as Cosigner_Quote_Set_UUID,
-- cqq.id As Cosigner_Quote_ID,
-- cqq.uuid As Cosigner_Quote_UUID,
-- cqq.accept_federal_loan As Cosigner_Quote_Loan_Type,
-- cqq.program_id As Cosigner_Quote_Program_ID,
-- cqq.lender_name As Cosigner_Quote_Lender_Name,
-- cqq.term_in_months As Cosigner_Loan_Term,
-- cqq.apr As Cosigner_Loan_APR,
-- cqq.monthly_payment As Cosigner_Loan_Pay,
IF(tentative_quote_uuid IS NOT NULL,1,0) As Quote_Accepted,
IF(selected_quote_uuid IS NOT NULL,1,0) As Lender_Accepted,
loan_key As Loan_Key
FROM leads_production.leads l
LEFT JOIN greenhouse_production.citizenship_statuses csb
ON csb.id = l.citizenship_status_ref
LEFT JOIN greenhouse_production.citizenship_statuses csc
ON csc.id = l.cosigner_citizenship_status_ref
LEFT JOIN core_production.quotes_quote_sets qqs
ON qqs.uuid = l.quote_set_uuid
LEFT JOIN core_production.quotes_quotes qq
ON qq.quote_set_id = qqs.id;
-- LEFT JOIN core_production.quotes_quote_sets cqqs
-- ON cqqs.uuid = l.borrower_cosigner_quote_set_uuid
-- LEFT JOIN core_production.quotes_quotes cqq
-- ON cqq.quote_set_id = qqs.id;
Please look at the commented lines in the above query. I want to write a query wherein the join is either on (qqs and qq tables) OR (cqqs and cqq tables) based on the value in borrower_cosigner_quote_set_uuid.
Something like this:
If borrower_cosigner_quote_set_uuid IS NOT NULL THEN
-- LEFT JOIN core_production.quotes_quote_sets cqqs
-- ON cqqs.uuid = l.borrower_cosigner_quote_set_uuid
-- LEFT JOIN core_production.quotes_quotes cqq
-- ON cqq.quote_set_id = qqs.id;
ELSE
LEFT JOIN core_production.quotes_quote_sets qqs
ON qqs.uuid = l.quote_set_uuid
LEFT JOIN core_production.quotes_quotes qq
ON qq.quote_set_id = qqs.id;`
Thanks in advance for your help.

You can conditionally JOIN using OR logic like so:
CREATE TABLE #temp1 ( foo INT );
CREATE TABLE #temp2 ( bar INT );
INSERT INTO #temp1
( foo )
VALUES ( 1 ),( 2 ),( NULL ),( 4 ),( 5 )
INSERT INTO #temp2
( bar )
VALUES ( 1 ),( 2 ),( 3 ),( 4 ),( 5 ),( 99 )
SELECT *
FROM #temp1
INNER JOIN #temp2 ON ( foo = bar AND foo IS NOT NULL)
OR ( foo IS NULL AND bar = 99 )
DROP TABLE #temp1
DROP TABLE #temp2
It's not a great example, but I want to JOIN any NULL value to 99 to produce:
foo bar
1 1
2 2
NULL 99
4 4
5 5
Hopefully you can follow the simplified logic to apply it to your problem.

Looke like you want a conditional join between TableA, TableB and TableC
If TableB and TableC have similar fields you can join with both tables and solve what field use by checking for the null value
SqlFiddle Demo
Setup Test db
CREATE TABLE TableA
(`Id` varchar(4), `keyA` int, `valor` int);
INSERT INTO TableA
(`Id`, `keyA`, `valor`)
VALUES
('1', 10, 90),('2', 20, 91),('3', 30, 92),(NULL, 40, 93);
CREATE TABLE TableB
(`Id` int, `valor` int);
INSERT INTO TableB
(`Id`, `valor`)
VALUES
(1, 200),(2, 201),(3, 202);
CREATE TABLE TableC
(`Id` int, `valor` int);
INSERT INTO TableC
(`Id`, `valor`)
VALUES
(10, 500),(20, 501),(30, 502),(40, 503);
QUERY
SELECT A.*,
IF(A.id is NULL, C.id, B.id) as joinkey,
IF(A.id is NULL, C.valor, B.valor) as valor
FROM TableA A
LEFT JOIN TableB B
ON A.id = B.id
LEFT JOIN TableC C
ON A.keyA = C.id
OUTPUT
| Id | keyA | valor | joinkey | valor |
|--------|------|-------|---------|-------|
| 1 | 10 | 90 | 1 | 200 |
| 2 | 20 | 91 | 2 | 201 |
| 3 | 30 | 92 | 3 | 202 |
| (null) | 40 | 93 | 40 | 503 |

Related

Find all sets/entities that are in another set [duplicate]

This question already has answers here:
Need a way to find matches between two many-to-many-relationships
(3 answers)
Closed 4 years ago.
The answer is found in the abstract here but I'm looking for the concrete SQL solution.
Given the following tables:
------------ -----------
| F_Roles | | T_Roles |
------+----- -----+-----
| FId | RId| |TId | RId|
------+------ -----+-----
| f1 | 2 | | t1 | 1 |
| f1 | 3 | | t1 | 2 |
| f2 | 2 | | t1 | 3 |
| f2 | 4 | | t1 | 4 |
| f2 | 9 | | t1 | 5 |
| f3 | 6 | | t1 | 6 |
| f3 | 7 | | t1 | 7 |
------------ ----------
(F_Roles) is a join table between F (not shown) and Roles (also not shown)
(T_Roles) is a join table between T (not shown) and Roles (not shown)
I need to return:
all (DISTINCT) FId's where the set of RId's for a given FId is a subset of (or 'IN') Roles. (I know I'm mixing Set Theory with database terms but only in the interest of better conveying the idea, I hope). So, f1 and f3 should be returned in this case, because the set of RId's for f1, {2,3}, and for f3, {6,7}, are subsets of T_Roles.
the list of RId's in T_Roles NOT found in any of the functions returned above. (T_Roles - (f1 Union f3)), or {1,4,5} in this example.
Let's define the following sample data:
DECLARE #F_Roles TABLE
(
[FID] CHAR(2)
,[RID] TINYINT
);
DECLARE #Roles TABLE
(
[RID] TINYINT
);
INSERT INTO #F_Roles ([FID], [RID])
VALUES ('f1', 2)
,('f1', 3)
,('f2', 2)
,('f2', 4)
,('f2', 9)
,('f3', 6)
,('f3', 7);
INSERT INTO #Roles ([RID])
VALUES (1), (2), (3), (4), (5), (6), (7);
No, the first query can be solved using the T-SQL statement below:
SELECT F.[FID]
FROM #F_Roles F
LEFT JOIN #Roles R
ON F.[RID] = R.[RID]
GROUP BY F.[FID]
HAVING SUM(CASE WHEN R.[RID] IS NULL THEN 0 ELSE 1 END) = COUNT(F.[RID]);
The idea is pretty simple. We are using LEFT join in order to check which RID from the #F_Roles table has corresponding RID in the #Rolestable. If it has not, the value returned by the query for the corresponding row is NULL. So, we just need to count the RIDs for each FID and to check if this count is equal to the count of values returned by the second table (NULL values are ignored).
The latter query is simple, too. Having the FID from the first, we just can use EXCEPT in order to found RIDs which are not matched:
SELECT [RID]
FROM #Roles
EXCEPT
SELECT [RID]
FROM #F_Roles
WHERE [FID] IN
(
SELECT F.[FID]
FROM #F_Roles F
LEFT JOIN #Roles R
ON F.[RID] = R.[RID]
GROUP BY F.[FID]
HAVING SUM(CASE WHEN R.[RID] IS NULL THEN 0 ELSE 1 END) = COUNT(F.[RID])
);
Here is the result of the execution of the queries:
For query 1:
with x as (
select f.fid, sum(case when r.rid is null then 1 end) as missing
from f_roles f
left join roles r on r.rid = r.rid
group by f.fid
)
select distinct f.fid
from f_roles f
join x on f.fid = x.fid
where x.missing = 0
For query 2:
with x as (
select f.fid, sum(case when r.rid is null then 1 end) as missing
from f_roles f
left join roles r on r.rid = r.rid
group by f.fid
),
y as (
select distinct f.fid
from f_roles f
join x on f.fid = x.fid
where x.missing = 0
)
select r.rid
from roles r
where r.rid not in (
select f.rid from y join f_roles f on f.rid = y.rid
)

Only use data from TableA when TableB has no matching entry

So i have:
Table A with (not only Name - Multiple Columns):
| IDA | Name |
|:-----------|------------:|
| 1 | John |
| 2 | Jonas |
| 3 | Carl |
| 4 | Foo |
| 5 | Bar |
| 6 | Dog |
Table B with (not only Name - Multiple Columns):
| IDB | Name |
|:-----------|------------:|
| 1 | Bob |
| 2 | Lisa |
Table MAIN with:
| ID | FKtoB | FKtoA |
|:-----------|------------:|------------:|
| 1 | 1 | 4 |
| 2 | | 3 |
| 3 | | 1 |
| 4 | 2 | 6 |
| 5 | | 2 |
| 6 | | 5 |
My goal is to select from MAIN and prefer to use the data of Table B but if not Available i will use the data of Table A. I tryed to use coalesce but that didn't help because i dont want to mix the data, so if for example Table B has the data for one row, then in this row there should be no data from Table A.
My Query looks like that:
select
coalesce(b.name, a.name) as surname, coalesce(b.surname, a.surname) as surname
from MAIN m
left join TableA a on a.IDA = m.FKtoA
left join TableB b on b.IDA = m.FKtoB
My Problem there is that if for example b.name is filled and b.surname isn't it would mix b.name with a.surname, thats not okay in my case.
Maybe you could add the non-existens of b as join criteria:
select
coalesce(b.name, a.name) as name, coalesce(b.surname, a.surname) as surname
from MAIN m
left join TableB b on b.IDA = m.FKtoB
left join TableA a on a.IDA = m.FKtoA and b.IDA is null
EDIT: corrected one surname to name
Try Left Join with Case -
SELECT
M.ID, (CASE WHEN B.IDB IS NOT NULL THEN B.Name ELSE A.Name END) AS NAME
FROM
MAIN AS M
LEFT JOIN TableB as B ON B.IDB = M.FKtoB
LEFT JOIN TableA as A ON A.IDA = M.FKtoA
From SQL Server 2012 (and higher) you can use IIF:
SELECT
IIF(m.FKtoB IS NULL, A.name, B.name) AS surname
FROM MAIN m
LEFT JOIN TableA a ON a.IDA = m.FKtoA
LEFT JOIN TableB b ON b.IDA = m.FKtoB
try this:
declare #tableA table(IDA INT,Name varchar(MAX))
declare #tableB table(IDB INT, Name VARCHAR(MAX))
declare #tableMain table(ID INT,FKtoB INT,FKtoA INT)
INSERT INTO #tableA
SELECT 1,'John'
union all
SELECT 2, 'Jonas'
union all
SELECT 3, 'Carl'
union all
SELECT 4,'Foo'
union all
SELECT 5 ,'Bar'
union all
SELECT 6,'Dog'
INSERT INTO #tableB
SELECT 1, 'Bob'
Union all
SELECT 2, 'Lisa'
INSERT INTO #tableMain
SELECT 1,1,4
union all
SELECT 2,null,3
union all
SELECT 3,null,1
union all
SELECT 4,2,6
union all
SELECT 5,null,2
union all
SELECT 6,null,5
Select tm.Id,ISNULL(tb.Name,ta.Name) As NAME from #tableMain tm
LEFT JOIN #tableB tb on tm.FktoB=tb.IDb and IDb is not NUll
LEFT JOIN #tableA tA on tm.FktoA=ta.IDA and FktoB is NUll
You want to select from table A only when there is no match in table B, so given foreign keys are intact:
select
coalesce(b.firstname, a.firstname) as firstname,
coalesce(b.surname, a.surname) as surname,
coalesce(b.birthday, a.birthday) as birthday,
...
from MAIN m
left join TableB b on b.IDB = m.FKtoB
left join TableA a on a.IDA = m.FKtoA and m.FKtoB is null;
Another approach would be union all:
select firstname, surname, birthday, ...
from TableB
where IDB in (select FKtoB from MAIN)
union all
select firstname, surname, birthday, ...
from TableA
where IDA in (select FKtoA from MAIN where FKtoB is null);
Try this. It will give result as you want.
(select ida as ID ,
case when ida is not null then ida end fkToIda,
case when idb is not null then idb end fkToIdB
from A
left outer join B on a.ida=b.idb)
union
(select idb ,
case when ida is not null then ida end,
case when idb is not null then idb end
from A
right outer join B on a.ida=b.idb)

SQL join that returns only records where all rows match

I have a query with a join on three tables. one of the columns in the 3rd table has a boolean value. . table 2 and table 3 are connected with product_id, each product_id on table 3 can be associated with true and false value as received value. I need a query to return all records in table 1 where are associated with products which their received value in table 3 has only true value.
In the sample data below I want to only return GHI
Table 1 - Sale
ID sale#
1 ABC
2 DEF
3 GHI
Table 2 PO Table 1 join Table 2 on Table1.ID = Table 2.SaleID
ID SaleID
1 1
2 1
3 2
4 3
5 3
Table 3
ID POID Received Table 2 right join table 3 on Table 2.ID = Table 3.POID
1 1 True
2 1 False
3 2 True
4 3 False
5 4 True
6 5 True
7 5 True
After the afternoon experimenting I make it work using a NOT IN, but it is very slow with my data set (which is only about 2000 records currently) I think it is probably because it is having to recreate the joins. It seems like there should be a more elegant way to accomplish this.
SELECT Distinct Table1.id, Table3.received
FROM Table3 INNER JOIN (Table2 INNER JOIN Table1 ON Table2.saleID = Table1.id)
ON Table3.POID = Table2.id
WHERE ((Table3.received)=True) and Table1.id NOT IN (
SELECT Table1.id
FROM Table3 INNER JOIN (Table2 INNER JOIN Table1 ON Table2.saleID = Table1.id)
ON Table3.POID = Table2.id
WHERE ((Table3.received)=False));
I believe this is the query you need
select
Table1.*
from
Table1 join Table2 on Table1.id = Table2.saleid
join table3 on table3.POID = Table2.ID
where
table3.received = true
first, only products have to be selected from table 3 that has true value entry in table3, this can be done by self join on POID. then the result can be joined with table2 and table1
select
Table1.*
from
Table1 join Table2
on Table1.id = Table2.saleid
join
(select t3.poid
from
Table3 t3 join Table3 t4
on t.POID = Table4.POID)
where t3.received = true and t4.received = true) all_true
on all_true.POID = Table2.ID
All you need to do is make sure that the count of records for a particular sale# is equal to the count of records with a value of received = True a.k.a. a count-if (which doesn't explicitly exist in SQL). The way you accomplish a count-if in SQL is to do a ...sum(case ... when ... then 1 else 0 end)....
Sample Data Setup:
create table dbo.Sale
(
ID int
, sale# char(3)
)
create table dbo.PO
(
ID int
, SaleID int
)
create table dbo.Received
(
ID int
, POID int
, Received char(5)
)
insert into dbo.Sale
values (1, 'ABC'), (2, 'DEF'), (3, 'GHI')
insert into dbo.PO
values (1,1), (2,1), (3,2), (4,3), (5,3)
insert into dbo.Received
values (1, 1, 'True')
, (2, 1, 'False')
, (3, 2, 'True')
, (4, 3, 'False')
, (5, 4, 'True')
, (6, 5, 'True')
, (7, 5, 'True')
Answer:
; with base as
(
select s.sale#
, p.SaleID
, r.POID
, r.Received
from dbo.Sale as s
inner join dbo.PO as p on s.ID = p.SaleID
inner join dbo.Received as r on p.ID = r.POID
)
, all_true as
(
--this sub-query is the filter for Sale#'s of interest
select b.sale#
from base as b
group by b.sale#
having sum(case b.Received when 'True' then 1 else 0 end) = count(*) --count-if = count
)
select b.*
from base as b
inner join all_true as t on b.sale# = t.sale#
Output:
+-------+--------+------+----------+
| sale# | SaleID | POID | Received |
+-------+--------+------+----------+
| GHI | 3 | 4 | True |
| GHI | 3 | 5 | True |
| GHI | 3 | 5 | True |
+-------+--------+------+----------+
Thanks tarheel
you put me on the track. I made the True/false a bit and added where Sum(received)= count(received)
SELECT DISTINCT Table1.id
FROM Table3 INNER JOIN (Table2 INNER JOIN Table1 ON Table2.saleID = Table1.id) ON Table3.POID = Table2.id
GROUP BY Table1.id
HAVING (-1*(Sum(Table3.received))=Count([Table3].[received]));

let union show values beside each other instead of below each other

I got a SQL query which displays values out of two tables below each other. Now I want the table to select the values out of the two different tables besides each other. This is my query right now:
(select i1,i2 from t1
except
select i1,i2 from t2)
union all
(select i1,i2 from t2
except
select i1,i2 from t1)
This is my sample data:
Data I have in table1:
i1 i2
---------
| 1 | 1 |
---------
| 2 | 2 |
---------
| 2 | 3 |
---------
data i have in table2:
i1 i2
---------
| 1 | 1 |
---------
| 2 | 3 |
---------
| 2 | 4 |
---------
outcome:
---------
| 2 | 2 | << this one comes from table 1
---------
| 2 | 4 | << this one comes from table 2
---------
wanted outcome:
t1 t2
-----------------
| 2 | 2 | 2 | 4 |
-----------------
I think the best way would be to use a FULL JOIN and then perform a WHERE with the NULL data. Because if you make a CROSS JOIN you would get more data than you need.
SELECT *
FROM t1
FULL JOIN t2
ON t1.i1 = 2.i1
AND t1.i2 = t2.i2
WHERE t1.Id IS NULL
OR t2.Id IS NULL
I'll explain with an example:
IF OBJECT_ID('tempdb..#t1') IS NOT NULL
DROP TABLE #t1
CREATE TABLE #t1
(
Id INT IDENTITY,
i1 INT,
i2 INT
)
INSERT INTO #t1
(
i1,i2
)
VALUES
(1,1)
,(2,2)
,(2,3)
,(2,6)
SELECT * FROM #t1
IF OBJECT_ID('tempdb..#t2') IS NOT NULL
DROP TABLE #t2
CREATE TABLE #t2
(
Id INT IDENTITY,
i1 INT,
i2 INT
)
INSERT INTO #t2
(
i1,i2
)
VALUES
(1,1)
,(2,3)
,(2,4)
,(2,5)
,(2,7)
SELECT * FROM #t2
SELECT *
FROM #t1
FULL JOIN #t2
ON #t1.i1 = #t2.i1
AND #t1.i2 = #t2.i2
WHERE #t1.Id IS NULL
OR #t2.Id IS NULL
SELECT *
FROM #t1 a
CROSS JOIN #t2 b
WHERE NOT EXISTS (SELECT 1
FROM #t2 c
WHERE a.i1 = c.i1
AND a.i2 = c.i2
)
AND NOT EXISTS (SELECT 1
FROM #t1 c
WHERE b.i1 = c.i1
AND b.i2 = c.i2
)
RESULT
In the first case you would get 5 records because (2,2) and (2,6) do not exist in t2, and (2,4), (2,5), (2,7) do not exist in t1. So you would have 5 results.
Id i1 i2 Id i1 i2
----------- ----------- ----------- ----------- ----------- -----------
2 2 2 NULL NULL NULL
4 2 6 NULL NULL NULL
NULL NULL NULL 3 2 4
NULL NULL NULL 4 2 5
NULL NULL NULL 5 2 7
(5 row(s) affected)
However, in the CROSS JOIN you would get 6 results because you would make a Cartesian product. 2 x 3 = 6 CROSS JOIN Explanation
Id i1 i2 Id i1 i2
----------- ----------- ----------- ----------- ----------- -----------
2 2 2 3 2 4
2 2 2 4 2 5
2 2 2 5 2 7
4 2 6 3 2 4
4 2 6 4 2 5
4 2 6 5 2 7
(6 row(s) affected)
You can do this with a CROSS JOIN and NOT EXISTS:
SELECT *
FROM t1 a
CROSS JOIN t2 b
WHERE NOT EXISTS (SELECT 1
FROM t2 c
WHERE a.i1 = c.i1
AND a.i2 = c.i2
)
AND NOT EXISTS (SELECT 1
FROM t1 c
WHERE b.i1 = c.i1
AND b.i2 = c.i2
)
A CROSS JOIN joins every record from one table with every record from the other, so every combination of rows is returned. NOT EXISTS is used to filter out records from t1 that ever appear in t2 and vice versa for the 2nd NOT EXISTS
try
SELECT *
FROM
(
SELECT i1, i2
FROM t1
EXCEPT
SELECT i1, i2
FROM t2
) a,
(
SELECT i1, i2
FROM t2
EXCEPT
SELECT i1, i2
FROM t1
) b

conditional joining in oracle

Conditional joining statement : -
High level Description :-
Join table based on two columns if combination is not present then join on one table -
Detailed Table -
create table tab1
(tab1_col1 number not null,
tab1_col2 number null,
tab1_col3 varchar(10));
Lookup Table
create table lkp1
(lkp_col1 number not null,
lkp_col2 number not null,
lkp_col3 number not null,
lkp_col4 varchar(10));
Insert Statement -
tab1
insert into tab1 values (10,101,'A');
insert into tab1 values (12,101,'B');
insert into tab1 values (11,102,'C');
insert into tab1 values (13,103,'B');
insert into tab1 values (14,104,'C');
insert into tab1 values (15,108,'A');
insert into tab1 values (16,102,'D');
Lookup Table
lkp1
insert into lkp1 values (10,101,50,'PICK');
insert into lkp1 values (10,101,50,'PICK');
insert into lkp1 values (11,102,100,'SKIP');
insert into lkp1 values (11,110,50,'PICK');
insert into lkp1 values (13,103,40,'PICK');
insert into lkp1 values (13,103,60,'PICK');
insert into lkp1 values (14,199,100,'PICK');
insert into lkp1 values (15,115,80,'PICK');
insert into lkp1 values (15,115,20,'PICK');
Requirement was -
Join table based on tab1_col1=lkp_col1
and
tab1_col2=lkp_col2
Filter out lookup table data lkp_col4=SKIP
If record not present in lookup table for then give default value(99.99).
(All records from tab1 table should be selected).
I built this query and it was working fine.
SELECT tab1_col1, tab1_col2, NVL (lkp_col3, '99.99') "LKP_COL3"
FROM tab1,
(SELECT *
FROM lkp1
WHERE lkp_col4 = 'PICK') lkp
WHERE tab1_col1 = lkp_col1(+) AND tab1_col2 = lkp_col2(+)
Now requirement changed
First check if
tab1_col1=lkp_col1
and
tab1_col2=lkp_col2
If lookup table is not having data for this combination
then check again with
tab1_col1=lkp_col1
If this is not also available then give dafault value.
Database - Oracle 10g
What I have tried so far
After lot of trail and error I m able to get the output. However, is there a better or simple way to use this ?
SELECT tab1_col1, tab1_col2, LKP_COL3
FROM tab1,
(SELECT *
FROM lkp1
WHERE lkp_col4 = 'PICK') lkp
WHERE tab1_col1 = lkp_col1 AND tab1_col2 = lkp_col2
union all
SELECT tab1_col1, tab1_col2, LKP_COL3
FROM tab1,
(SELECT *
FROM lkp1
WHERE lkp_col4 = 'PICK') lkp
WHERE tab1_col1 = lkp_col1(+)
AND
LKP_COL1|| '-' || LKP_COL2 not in( SELECT tab1_col1|| '-' || tab1_col2
FROM tab1, lkp1 lkp
WHERE tab1_col1 = lkp_col1 AND tab1_col2 = lkp_col2)
order by 1
The following result:
| TAB1_COL1 | TAB1_COL2 | LKP_COL3 |
|-----------|-----------|----------|
| 10 | 101 | 50 |
| 11 | 102 | 50 |
| 12 | 101 | 99.99 |
| 13 | 103 | 40 |
| 13 | 103 | 60 |
| 14 | 104 | 100 |
| 15 | 108 | 20 |
| 15 | 108 | 80 |
| 16 | 102 | 99.99 |
was produced by this query:
SELECT DISTINCT
tab1.tab1_col1
, tab1.tab1_col2
, COALESCE(lkp1.lkp_col3, lkp2.lkp_col3, 99.99) "LKP_COL3"
FROM tab1
LEFT JOIN lkp1
ON tab1.tab1_col1 = lkp1.lkp_col1
AND tab1.tab1_col2 = lkp1.lkp_col2
AND lkp1.lkp_col4 = 'PICK'
LEFT JOIN lkp1 lkp2
ON tab1.tab1_col1 = lkp2.lkp_col1
AND lkp2.lkp_col4 = 'PICK'
ORDER BY
tab1.tab1_col1
, tab1.tab1_col2
;
DISTINCT was added because the second left (outer) join produces unwanted repetition in the output.
refer to this sqlfiddle