select a value from different table based on conditions in sql - sql

I'm trying to select a value from a different table based on current table values and condition
Table 1:
C1
C2
C3
1
2
3
1
4
5
1
6
6
2
3
3
Table 2:
D1
D2
D3
D4
1
2
3
Value1
1
4
5
Value2
1
6
8
Value3
2
3
4
Value4
2
Value5
And Im trying to get the below expected result table a single line sql
Results:
C1
C2
C3
D4
1
2
3
Value1
1
4
5
Value2
1
6
6
2
3
3
Value5
The condition is to pick D4 value only
(C1=D1 and C2=D2 and C3=D3) matches then D4 or when C1=D1 matches then D4 else null for all
I tried inner join and also case statement but no success
Here is the fiddle i had created

This looks like a left join:
select t1.*, t2.d4
from table1 t1 left join
table2 t2
on t1.C1 = t2.D1 and
(t1.C2 = t2.D2 or t2.D2 is null) and
(t1.C3 = t2.D3 or t2.D3 is null);
Note: It is a little hard to tell from the explanation if you need for both D2 and D3 to be NULL. If so:
select t1.*, t2.d4
from table1 t1 left join
table2 t2
on t1.C1 = t2.D1 and
(t1.C2 = t2.D2 and t1.C3 = t2.D3 or
t2.D2 is null and t2.D3 is null
);
Here is the fiddle.

Related

Update the changed row of target table only using source table if there is any value mismatch between 2 columns

Table T1
ID C1 C2 C3
-- -- -- --
1 x y z
2 p q r
3 a b c
Table T2
1 x y z
2 p q1 r
3 a b c1
Need to update all values of T2 into T1 to ensure both table should have same value.This can be achieved by merge statement.But in table T1 has a column update_timestamp which will update only if there is any mismatch between 2 table.In merge the update_timestamp updates if there is no mismatch also.In above example the update_timestamp column update for ID no 2 & 3 only.
MERGE INTO T1
USING T2
ON (T1.ID = T2.ID)
WHEN MATCHED THEN
UPDATE SET T1.C1 = T2.C1,T1.C2 = T2.C2,T1.C3 = T2.C3,T1.update_timestamp=SYSDATE;
Try this one (in case you track the changes for all 3 columns - c1, c2 and c3):
MERGE INTO T1
USING (
select id, c1, c2, c3 from T2
minus
select id, c1, c2, c3 from T1
) T2
ON (T1.ID = T2.ID)
WHEN MATCHED THEN
UPDATE SET T1.C1 = T2.C1,T1.C2 = T2.C2,T1.C3 = T2.C3,T1.update_timestamp=SYSDATE;

compare rows between two ids with in the same table and insert the missing row for that id

i have a table which has structure mentioned below
let's say table name -> tab1
id c1 c2 c3 c4
1 a b 01-02-18 c row1
1 o b 01-02-18 c row2
1 a b 04-05-16 c row3
1 n g 01-02-18 d row4
2 a b 01-02-18 c row5
So i want to insert id 1 rows to id 2. As data for row1 and row5 is same for column c1,c2,c3,c4 so i want to skip row1 to be inserted for id 2 .
Table should look like this
id c1 c2 c3 c4
1 a b 01-02-18 c row1
1 o b 01-02-18 c row2
1 a b 04-05-16 c row3
1 n g 01-02-18 d row4
2 a b 01-02-18 c row5
2 o b 01-02-18 c row6
2 a b 04-05-16 c row7
2 n g 01-02-18 d row8
i have written this query but doesn't give me the expected result
for selecting the unique record based on column :
select Count(*) FROM tab1 A
WHERE Not EXISTS
(select * from tab1 B where A.c1 = B.c1 AND A.c2 = B.c2 AND A.c3= B.c3
AND A.c4 = B.c4
and B.id=2 )and A.id = 1;
for inserting the records
insert into rsk_mdl_sec_map_ts
select '2', c1, c2, c3, c4
FROM tab1 A
WHERE Not EXISTS
(select * from tab1 B where A.c1 = B.c1 AND A.c2 = B.c2 AND A.c3= B.c3
AND A.c4 = B.c4
and B.id=2 )and A.id = 1;
can anyone help what is wrong in this or suggest me some other approach to achieve the same . Thanks
First build a query that pick rows which should be insered and omits those that already exist as id=2 :
SELECT *
FROM tab1 t1
WHERE id = 1
AND NOT EXISTS (
SELECT 'anything' FROM tab1 t2
WHERE t1.c1=t2.c1
AND t1.c2=t2.c2
AND t1.c3=t2.c3
AND t1.c4=t2.c4
AND id = 2
)
| ID | C1 | C2 | C3 | C4 |
|----|----|----|-----------------------|----|
| 1 | o | b | 2018-01-02 00:00:00.0 | c |
| 1 | a | b | 2016-04-05 00:00:00.0 | c |
| 1 | n | g | 2018-01-02 00:00:00.0 | d |
Demo: http://sqlfiddle.com/#!4/d66fc/4
Next, use INSERT ... SELECT .... command, just put INSERT above the SELECT command, and use 2 constant as ID, and DISTINCT clause to remove possible duplicates:
INSERT into tab1( id, c1, c2, c3, c4 )
SELECT DISTINCT 2, c1, c2, c3, c4
FROM tab1 t1
WHERE id = 1
AND NOT EXISTS (
SELECT 'anything' FROM tab1 t2
WHERE t1.c1=t2.c1
AND t1.c2=t2.c2
AND t1.c3=t2.c3
AND t1.c4=t2.c4
AND id = 2
)
Using your test data, we can do the following cross join - which will give us each ID combined with all rows that have id 1:
select
T2.id
, T1.c1
, T1.c2
, T1.c3
, T1.c4
from (
select *
from tab1
where id = 1
) T1, ( select unique id from tab1 ) T2
;
-- result
ID C1 C2 C3 C4
1 a b 01-FEB-18 c
1 o b 01-FEB-18 c
1 a b 04-MAY-18 c
1 n g 01-FEB-18 d
2 a b 01-FEB-18 c
2 o b 01-FEB-18 c
2 a b 04-MAY-18 c
2 n g 01-FEB-18 d
Then, use the MINUS operator and insert all resulting rows.
insert into tab1 ( id, c1, c2, c3, c4 )
(
select
T2.id
, T1.c1
, T1.c2
, T1.c3
, T1.c4
from (
select *
from tab1
where id = 1
) T1, ( select unique id from tab1 ) T2
)
minus -- do not insert existing rows
select * from tab1
;
3 rows inserted.
Tab1 now contains:
select * from tab1 ;
ID C1 C2 C3 C4
1 a b 01-FEB-18 c
1 o b 01-FEB-18 c
1 a b 04-MAY-18 c
1 n g 01-FEB-18 d
2 a b 01-FEB-18 c
2 a b 04-MAY-18 c
2 n g 01-FEB-18 d
2 o b 01-FEB-18 c
See dbfiddle for more details.
The simplest solution is to use MERGE:
merge into tab1
using ( select 2 as id, c1, c2, c3, c4
from tab1
where id = 1 -- optional
) q
on (q.id = tab1.id
and q.c1 = tab1.c1
and q.c2 = tab1.c2
and q.c3 = tab1.c3
and q.c4 = tab1.c4)
when not matched then
insert values (q.id, q.c1, q.c2, q.c3, q.c4)
;
This solution will work provided tab1(id, c1, c2, c3, c4) defines a set of unique rows.
Here is a demo on SQL Fiddle.
simply create a temporary table TMP_TABLE to do full join
CREATE TABLE TMP_TABLE AS SELECT *
FROM
(SELECT DISTINCT id FROM tab1 ) a,
(SELECT DISTINCT c1, c2, c3 FROM tab1 ) b

SQL Server 2008, how to join tables on different attributes [duplicate]

This question already has answers here:
How to do an inner join on row number in sql server
(2 answers)
Closed 6 years ago.
I have two tables like this:
Table A:
ID VAL
1 10
2 20
3 30
4 40
5 50
Table B:
ID VAL2
sd 50
gh 80
dv 90
bf 100
ww 45
Joined table:
ID Val VAL2
1 10 50
2 20 100
3 30 45
4 40 80
5 50 90
So, ID in table A is matched to an ID in table B
1 - sd, 2 - bf, 3 - ww, 4 - gh, 5 - dv
How can I join these two?
select A.ID, A.VAL, B.Val
from tableA A
**left join tableB B on A.ID = B.ID ??**
Thank you!
One option here, which does not require the use of a temporary table, would be to create an inline table containing the mappings of table A's ID values to table B's ID values.
SELECT t1.ID AS ID
t1.VAL AS Val,
t3.VAL2 AS Val2
FROM tableA t1
INNER JOIN
(
SELECT 1 AS IDA, 'sd' AS IDB
UNION ALL
SELECT 2 AS IDA, 'bf' AS IDB
UNION ALL
SELECT 3 AS IDA, '22' AS IDB
UNION ALL
SELECT 4 AS IDA, 'gh' AS IDB
UNION ALL
SELECT 5 AS IDA, 'dv' AS IDB
) t2
ON t1.ID = t2.IDA
INNER JOIN tableB t3
ON t2.IDB = t3.ID
SELECT a.ID, a.VAL, B.VAL2 FROM
(
SELECT CASE WHEN ID = 'sd' THEN 1
WHEN ID = 'bf' THEN 2
WHEN ID = 'ww' THEN 3
WHEN ID = 'gh' THEN 4
WHEN ID = 'dv' THEN 5
END AS ID, VAL2 FROM tableB
) AS t INNER JOIN tableA a ON a.ID = t.Id

Create view from 3 tables

I have 3 tables.
table1
id info1 info2
1 a b
2 a b
3 a b
4 a b
table2
id table1_id column_id value
1 1 1 10
2 1 2 20
3 1 3 30
4 2 1 40
5 2 2 50
6 2 3 60
7 3 1 70
8 3 2 80
9 3 3 90
10 4 1 100
11 4 2 110
12 4 3 120
table3
column_id column
1 column1
2 column2
3 column3
Based on the above, I need to create a view which would convert rows to columns in the following way:
column1 column2 column3
10 20 30
40 50 60
70 80 90
100 110 120
Is it possible to create a view like the above?
You can use below if you use oracle 11g or above you can use pivot also.
SELECT max(CASE
WHEN column1 = 'column1'
THEN value1
END) column1
,max(CASE
WHEN column1 = 'column2'
THEN value1
END) column2
,max(CASE
WHEN column1 = 'column3'
THEN value1
END) column3
FROM (
SELECT t2.table1_id
,t3.column1
,to_char(t2.value1) AS value1
FROM table2 t2
JOIN table1 t1 ON t1.id1 = t2.table1_id
JOIN table3 t3 ON t3.column_id = t2.column_id
)
GROUP BY table1_id
The short answer to the question is yes, a solution to the problem could be to join the tables and then pivot them.
I have written some code as a suggestion to help you along, this is untested code and you will have to tweak it a bit
select * from (
select T1.id as Row, T3.column, T2.value
from table1 T1
left join table2 T2 on T2.table1_id = T1.id
left join table3 T3 on T3.column_id = T2.column_id
)
pivot
(
sum(value)
for value in ('column1','column2','column3')
)
group by row
order by row

Joining two tables in a select

I have two tables:
TABLE 1
ID VALUE
1 ABC
2 DEF
3 GHI
4 JKL
5 XYZ
TABLE 2
ID T1_ID VALUE
1 1 A
2 1 B
3 2 A
4 3 A
5 3 B
6 4 B
I want to select all rows from TABLE 1 which have a TABLE 2 row for Values A AND B.
This would be rows 1 and 3 (not 2 because it has only A, not 4 because it has only B).
Can I do this without a subquery?
(Note: I also need to query against values in table 1 so I can't just query table 2.)
Tadaaah! Without a subquery.
select distinct
t1.*
from
Table1 t1
inner join Table2 t2a on t2a.t1_ID = t1.ID and t2a.VALUE = 'A'
inner join Table2 t2b on t2b.t1_ID = t1.ID and t2b.VALUE = 'B'
SELECT t1.ID,
t1.VALUE
FROM Table1 t1
JOIN Table2 t2
ON t1.ID = t2.T1_ID
WHERE t2.VALUE IN ( 'A', 'B' )
GROUP BY t1.ID,
t1.VALUE
HAVING COUNT(DISTINCT t2.VALUE) = 2