sql select values from another table if exist - sql

Please help, need to select from table 1, but if entry with the same id exists in table2 should return name and last name from there otherwise values from table1
table1
id|name|lastname
1 | |
2 | |
3 | |
table2
id|name|lastname
3 | |
Tried this, but not working
SELECT ID, NAME, LASTNAME
FROM table1
WHERE EXISTS
(SELECT 1 FROM table2 WHERE table2.ID = table1.ID)

if entry with the same id exists in table2 should return name and last name from there otherwise values from table1
You want a LEFT OUTER JOIN and then to use COALESCE:
SELECT t1.id,
COALESCE( t2.name, t1.name ) AS name,
COALESCE( t2.lastname, t1.lastname ) AS last_name
FROM table1 t1
LEFT OUTER JOIN table2 t2
ON ( t1.id = t2.id )
Which, for your sample data:
CREATE TABLE table1 ( id, name, lastname ) AS
SELECT 1, 'Alice1', 'Abbot1' FROM DUAL UNION ALL
SELECT 2, 'Betty1', 'Baron1' FROM DUAL UNION ALL
SELECT 3, 'Carol1', 'Casey1' FROM DUAL;
CREATE TABLE table2 ( id, name, lastname ) AS
SELECT 3, 'Carol2', 'Casey2' FROM DUAL;
Outputs:
ID
NAME
LAST_NAME
3
Carol2
Casey2
2
Betty1
Baron1
1
Alice1
Abbot1
db<>fiddle here

Related

How to force LEFT OUTER JOIN return NULL or empty?

SELECT table1.id, table2.name
FROM table1
LEFT JOIN table2
ON table1.id = table2.id;
so if table1.id = NULL I want to return NULL or empty string from table2, i.e.
ID, NAME
1 name1
2 name2
null null
3 name3
but now getting "column ambiguously defined" error since table2 has many NULLs in ID column
It does return what you want, without any errors:
SELECT table1.id, table2.name
FROM table1
LEFT JOIN table2
ON table1.id = table2.id;
Which, for the sample data:
CREATE TABLE table1 ( id ) AS
SELECT 1 FROM DUAL UNION ALL
SELECT 2 FROM DUAL UNION ALL
SELECT NULL FROM DUAL UNION ALL
SELECT 3 FROM DUAL;
CREATE TABLE table2 ( id, name ) AS
SELECT 1, 'name1' FROM DUAL UNION ALL
SELECT 2, 'name2' FROM DUAL UNION ALL
SELECT 3, 'name3' FROM DUAL;
Outputs:
ID | NAME
---: | :----
1 | name1
2 | name2
3 | name3
null | null
db<>fiddle here

How to find the same elements in tow arrays of two different tables in HIVE?

I have two tables like the follows:
table1:
id sid
1 | ['101', '102', '103']
2 | ['102', '101', '103']
3 | ['103', '101', '102']
table2:
id | sid
1 | ['101', '102', '103']
3 | ['102', '103']
and I wish to get the following table:
id sid
1 | ['101', '102', '103']
2 | ['102', '101', '103']
3 | ['103', '102']
Explanation: I wish to select the same elements in table1.sid and table2.sid with the same order in table1. Besides, if the id in table1 doesn't exist in table2, then keep the sid as it is in table1. What should I do?
You can use posexplode() to basically do what you want. Of course, all this array stuff is more complex in Hive than in other databases, particularly getting the results in the order you want:
select t1.id, collect_list(sid2)
from (select t1.id, t2.sid2, t1.pos1
from (table1 t1 lateral view
posexplode(t1.sid) as pos1, sid1
) left join
(table2 t2 lateral view
posexplode(t2.sid) as pos2, sid2
)
on t2.id = t1.id and t2.sid2 = t1.sid1
distribute by t1.id
order by t1.id, t1.pos1
) t
Something like this:
with t as (
select t1.id, collect_list(sid2) as sid
from (select t1.id, t2.sid2, t1.pos1
from (table1 t1 lateral view
posexplode(t1.sid) as pos1, sid1
) left join
(table2 t2 lateral view
posexplode(t2.sid) as pos2, sid2
)
on t2.id = t1.id and t2.sid2 = t1.sid1
distribute by t1.id
order by t1.id, t1.pos1
) t
select t1.id,
(case when size(t.sid) = 0 then t1.sid else t.sid end)
from t1 left join
t
on t1.id = t.id

Return different rows between two tables

Is there a way to check and return all rows that are not common between two tables?
Table 1:
pk name date
102 John 1/1/16
101 Bob 1/1/17
Table 2:
pk name date
102 John 1/1/16
104 Bob 1/1/17
105 Ted 1/1/18
Ideally, I can also limit the query by date. So If I limit by Date < 1/1/18, the result would be:
table pk name date
1 101 Bob 1/1/17
2 104 Bob 1/1/17
select * from table1
union
select * from table2
except
(select * from table1 intersect select * from table2)
select * from table1 t1
where not exsits (
select 1 from table2 t2 where t2.pk = t1.pk
) and t1.Date < '2018/1/1'
union all
select * from table2 t2
where not exsits (
select 1 from table1 t1 where t2.pk = t1.pk
) and t2.Date < '2018/1/1'
You can use EXCEPT for this like
select pk,
name,
date from table1
except
select pk,
name,
date from table2;
(OR) using NOT IN operator along with UNION like
select * from table1 where pk not in (select distinct pk from table2);
union
select * from table2 where pk not in (select distinct pk from table1);
To be more precise with your sample data:
SELECT * FROM
(( SELECT 1 as [table],* FROM
(SELECT * FROM #TABLE_1
EXCEPT
SELECT * FROM #TABLE_2) AS Inner1)
UNION
(SELECT 2 as [table],* FROM
(SELECT * FROM #TABLE_2
EXCEPT
SELECT * FROM #TABLE_1) AS Inner2)) AS Final
WHERE Final.date < '2018-01-01'

Get groups that are exactly equal to a table

I have a query that groups easily. I need to get the groups that have exactly the same records to another table (relationship).
I'm using ANSI-SQL under SQL Server, but I accept an answer of any implementation.
For example:
Table1:
Id | Value
---+------
1 | 1
1 | 2
1 | 3
2 | 4
3 | 2
4 | 3
Table2:
Value | ...
------+------
1 | ...
2 | ...
3 | ...
In my example, the result is:
Id |
---+
1 |
How imagined that it could be the code:
SELECT Table1.Id
FROM Table1
GROUP BY Table1.Id
HAVING ...? -- The group that has exactly the same elements of Table2
Thanks in advance!
You can try the following:
select t1.Id
from Table2 t2
join Table1 t1 on t1.value = t2.value
group by t1.Id
having count(distinct t1.value) = (select count(*) from Table2)
SQLFiddle
To get the same sets use an inner join:
SELECT Table1.Id
FROM Table1
INNER JOIN table2 ON table1.id=table2.id
GROUP BY Table1.Id
HAVING ...? --
CREATE TABLE #T1 (ID INT , [Values] INT) INSERT INTO #T1 VALUES (1,1),(1,2),(1,3),(2,4),(2,5),(3,6)
CREATE TABLE #T2 ([Values] INT) INSERT INTO #T2 VALUES (1),(2),(3),(4)
SELECT * FROM #T1
SELECT * FROM #T2
SELECT A.ID
FROM
( SELECT ID , COUNT(DISTINCT [Values]) AS Count FROM #T1
GROUP BY ID
) A
JOIN
(
SELECT T1.ID, COUNT(DISTINCT T2.[Values]) Count
FROM #T1 T1
JOIN #t2 T2
ON T1.[Values] = T2.[Values]
GROUP BY T1.ID
) B
ON A.ID = B.ID AND A.Count = B.Count

Within a SQL Server view - how to combine multiple column results into one column

I have a SQL Server database with the following 2 tables:
I have created a view with the following query and results:
My question is what query would bring the (3) ID columns in 'Table2' into one master ID List to where the final result would look like this:
ID Table1ID
test1 1
test1 4
test2 1
test2 2
test3 1
test3 2
test3 3
Note: here is the view as shown above:
SELECT
dbo.Table1.Description, Table2_1.ID AS Table2ID_1, Table2_2.ID AS Table2ID_2,
dbo.Table2.ID AS Table2ID_3
FROM
dbo.Table1
LEFT OUTER JOIN
dbo.Table2 ON dbo.Table1.ID = dbo.Table2.Table1ID3
LEFT OUTER JOIN
dbo.Table2 AS Table2_2 ON dbo.Table1.ID = Table2_2.Table1ID2
LEFT OUTER JOIN
dbo.Table2 AS Table2_1 ON dbo.Table1.ID = Table2_1.Table1ID1
My suggestion would be to UNPIVOT the data in Table2 so you can easily join on the data, then you can return the table1 description and the table2 id. The UNPIVOT portion of this query using CROSS APPLY:
select col, value, t2.Id
from table2 t2
cross apply
(
select 'table1id1', table1id1 union all
select 'table1id2', table1id2 union all
select 'table1id3', table1id3
) c (col, value);
See SQL Fiddle with Demo. This gives a result:
| COL | VALUE | ID |
---------------------------
| table1id1 | 1 | 1 |
| table1id2 | 2 | 1 |
| table1id3 | 3 | 1 |
| table1id1 | 2 | 2 |
| table1id2 | 3 | 2 |
| table1id3 | (null) | 2 |
| table1id1 | 3 | 3 |
Now that you have the data in rows, you can easily join on the value column to return the id:
select t1.description,
d.id
from table1 t1
inner join
(
select col, value, t2.Id
from table2 t2
cross apply
(
select 'table1id1', table1id1 union all
select 'table1id2', table1id2 union all
select 'table1id3', table1id3
) c (col, value)
) d
on t1.id = d.value
order by t1.description, d.id;
See SQL Fiddle with Demo
If you really want to use UNPIVOT, then you can use the following which doesn't join on each table multiple times to get the result:
select t1.description, t2.id
from table1 t1
inner join
(
select id, col, value
from
(
select id, [Table1ID1], [Table1ID2], [Table1ID3]
from table2
) d
unpivot
(
value for col in ([Table1ID1], [Table1ID2], [Table1ID3])
) unpiv
) t2
on t1.id = t2.value
order by t1.description, t2.id;
See SQL Fiddle with Demo.
The UNPIVOT and the CROSS APPLY is doing the same thing as a UNION ALL query:
select t1.description, t2.id
from table1 t1
inner join
(
select id, 'table1id1' col, table1id1 value
from table2
union all
select id, 'table1id2' col, table1id2
from table2
union all
select id, 'table1id3' col, table1id3
from table2
) t2
on t1.id = t2.value
order by t1.description, t2.id;
See SQL Fiddle with Demo
Microsoft SQL Server 2005 and higher support an UNPIVOT statement making the CROSS APPLY unnecessary.
SELECT Description AS [ID], Table1ID
FROM (SELECT Table1.Description, Table2_1.ID AS Table2ID_1, Table2_2.ID AS Table2ID_2, Table2.ID AS Table2ID_3
FROM Table1 LEFT OUTER JOIN
Table2 ON Table1.ID = Table2.Table1ID3 LEFT OUTER JOIN
Table2 AS Table2_2 ON Table1.ID = Table2_2.Table1ID2 LEFT OUTER JOIN
Table2 AS Table2_1 ON Table1.ID = Table2_1.Table1ID1) AS pvttbl
UNPIVOT ( Table1ID FOR ID IN (Table2ID_1, Table2ID_2, Table2ID_3)) AS unpvttbl
ORDER BY Description, Table1ID
See Using PIVOT and UNPIVOT on MSDN.