Extract ang join from same column in Hive - hive

I have a requirement to have different data from single column from another table.
Lets say I have a TAB_A with below sets of columns.
TAB_B has one column.
My expected out put should be,
Here col_x should have the data when code(TAB_B) = '08'
and
col_y should have the data when code(TAB_B) = '36'.
Whatever I have tried is not working,
SELECT
a.col1,
a.col2,
a.col3,
a.col4,
substr(a.col5,13,3) as col_x,
substr(a.col5,13,3) as col_y
from TAB_A a
JOIN TAB_B b on b.code = '08'
JOIN TAB_B b on b.code = '36'
Can anyone please suggest the best solution.

You requirement is not pretty clear but seems you are looking for cross join and case when clause
SELECT
a.col1,
a.col2,
a.col3,
a.col4,
case when code(TAB_B) = '08' then substr(a.col5,13,3) else null end as col_x,
case when code(TAB_B) = '36'then substr(a.col5,13,3) else null end as col_y,
from TAB_A a
JOIN TAB_B
;

Related

Can I replace Union all with any kind on joins?

I have the below query for negative testing, But I want to replace the union all if possible.
select A.*
from A
join B
on A.COL1=B.COL1
where B.COL3 is null
union all
select A.*
from A
join B
on A.COL2=B.COL4
where B.COL5 is null;
Need to get data from both SQL without using union all
You could combine the two queries into a single join and collapse the where condition into it:
select A.*
from A
join B on (A.COL1 = B.COL1 and B.COL3 is null) or
(A.COL2 = B.COL4 and B.COL5 is null)
Since you're only after data from Table A you don't need the join to table B at all and can re-write this as an Exists...
SELECT A.*
FROM A
WHERE EXISTS (SELECT 1
FROM B
WHERE A.COL1=B.COL1 and B.COL3 is null)
OR EXISTS (SELECT 1
FROM B
WHERE A.COL2=B.COL4 and B.COL5 is null)
But this has likely has two issues:
I'm pretty sure if you look at the execution plan for both; you'll find the union all is more efficient because it operates at a set level instead of a row level ad the OR needed in this is slower.
This will return 1 record from A instead of 2 from that of a union all. had it been a union; this should/would return the same results and avoid the union. But simply put you want the same data from A twice (or more depending on cardinality of joins)
SELECT A.*
FROM A
JOIN B ON (A.COL1 = B.COL1 OR A.COL2 = B.COL4) AND B.COL3 IS NULL;

SQL to Match columns from 2 different tables using a Select statement

I have 2 tables A & B with columns 6 columns in each table.
Table A has lesser rows than table B.
I want to write a Select Statement where if the below condition satisfies
-----A.Col1=B.Col1 and A.Col2=B.Col2 and A.Col3=B.Col3 and A.Col4=B.Col4 and A.Col5=B.Col5 and A.Col6=B.Col6-----
if all conditions are satisfied then in a new column say "Match" else "NoMatch"
How do I do that ?
I would suggest using exists. If you want a new column in A:
select a.*,
(case when exists (select 1
from b
where A.Col1 = B.Col1 and A.Col2 = B.Col2 and
A.Col3 = B.Col3 and A.Col4 = B.Col4 and
A.Col5 = B.Col5 and A.Col6 = B.Col6
)
then 'match' else 'nomatch'
end) as flag
from a;
Note: If you want the new column on B, the logic is the same but the two tables are reversed.
If any of the columns can have NULL values, then you need to take that into account.
You can use CASE statement and I am considering that you need all data from tableB and matching data from tableA as follows:
select b.*, a.*,
case when A.Col1=B.Col1 and A.Col2=B.Col2
and A.Col3=B.Col3 and A.Col4=B.Col4
and A.Col5=B.Col5 and A.Col6=B.Col6
then 'Match'
else 'No match'
end as res
from tableB b
left join TableA a
on A.Col1=B.Col1 and A.Col2=B.Col2
and A.Col3=B.Col3 and A.Col4=B.Col4
and A.Col5=B.Col5 and A.Col6=B.Col6

Select one record from left table, but multiple from right table

I have two tables, where I want to select all the data where it matches on identifier, however I want to replace the repeated data collected from table A to NULL. My current result is shown in the Current Table (refer to attached image). I want results displayed as shown in New Table.
My Current SQL is:
SELECT
a.name, a.desc, b.seq
from table_a a, table_b b
where a.name = b.name
I believe I can possibly do this by using CASE:
CASE
WHEN
b.seq = 1 THEN a.name, a.desc ELSE a.name IS NULL, a.desc IS NULL
END
But I'm not having any luck. Any help please?
Thank you!
Use the CASE clause:
select
case when b.seq = 1 then a.name end,
case when b.seq = 1 then a.desc end,
b.seq
from table_a a
join table_b b on a.name = b.name

SQL -How to recreate this logic using a sql case statement in side a where clause

I'm still in learning phase, please help me in getting the following query resolved:
I got a logic in one query as:
select val =
CASE
WHEN tbl.ReqNo LIKE '456%' THEN 'Value A'
ELSE 'Value B'
END
From tblA tbl
Now I need to use this logic to filter another query:
SELECT B.col1, A.col1, A.col2
FROM
tblB B
INNER JOIN tblA A
ON B.ID = A.ID
WHERE
B.BID = 123
AND B.BName = "sth"
AND B.Address = "123 St ..."
Can anyone help me on how I can use the case statement logic in the second query's WHERE clause to filter the results.
try this
SELECT B.col1, A.col1, A.col2
FROM
tblB B
INNER JOIN tblA A
ON B.ID = A.ID
WHERE
B.BID = 123
AND B.BName = "sth"
AND B.Address = "123 St ..." and
ColumnName = CASE
WHEN tblA.BName LIKE '456%' THEN 'Value A'
ELSE 'Value B'
END
but i do not recommend use case in where

Compare the data in two tables with same schema

I have been doing a bit of searching for a while now on a particular problem, but I can't quite find this particular question
I have a rather unusual task to achieve in SQL:
I have two tables, say A and B, which have exactly the same column names, of the following form:
id | column_1 | ... | column_n
Both tables have the same number of rows, with the same id's, but for a given id there is a chance that the rows from tables A and B differ in one or more of the other columns.
I already have a query which returns all rows from table A for which the corresponding row in table B is not identical, but what I need is a query which returns something of the form:
id | differing_column
----------------------
1 | column_1
3 | column_6
meaning that the row with id '1' has different 'column_1' values in tables A and B, and the row with id '3' has different 'column_6' values in tables A and B.
Is this at all achievable? I imagine it might require some sort of pivot in order to get the column names as values, but I might be wrong. Any help/suggestions much appreciated.
Yes you can do that with a query like this:
WITH Diffs (Id, Col) AS (
SELECT
a.Id,
CASE
WHEN a.Col1 <> b.Col1 THEN 'Col1'
WHEN a.Col2 <> b.Col2 THEN 'Col2'
-- ...and so on
ELSE NULL
END as Col
FROM TableOne a
JOIN TableTwo b ON a.Id=b.Id
)
SELECT Id, Col
WHERE Col IS NOT NULL
Note that the above query is not going to return all the columns with differences, but only the first one that it is going to find.
You can do this with an unpivot -- assuming that the values in the columns are of the same type.
If your data is not too big, I would just recommend using a bunch of union all statements instead:
select a.id, 'Col1' as column
from a join b on a.id = b.id
where a.col1 <> b.col1 or a.col1 is null and b.col1 is not null or a.col1 is not null and b.col1 is null
union all
select a.id, 'Col2' as column
from a join b on a.id = b.id
where a.col2 <> b.col2 or a.col2 is null and b.col2 is not null or a.col2 is not null and b.col2 is null
. . .
This prevents issues with potential type conversion problems.
If you don't mind having the results on one row, you can do:
select a.id,
(case when a.col1 <> b.col1 or a.col1 is null and b.col1 is not null or a.col1 is not null and b.col1 is null
then 'Col1;'
else ''
end) +
(case when a.col2 <> b.col2 or a.col2 is null and b.col2 is not null or a.col2 is not null and b.col2 is null
then 'Col2;'
else ''
end) +
. . .
from a join b on a.id = b.id;
If your columns are of the same type, there is a slick method:
SELECT id,col
FROM (SELECT * FROM A UNION ALL SELECT * FROM B) t1
UNPIVOT (value for col in (column_1,column_2,column_3,column_4)) t2
GROUP BY id,col
HAVING COUNT(DISTINCT value) > 1
If you need to handle NULL as a unique value, then use HAVING COUNT(DISTINCT ISNULL(value,X)) > 1 with X being a value that doesn't occur in your data