Hive query or pig script to resolve the below mentioned issue - hive

I have one table with below data:
A
B
C
D
E
output should like
AB
AC
AD
AE
BC
BD
BE
CD
CE
DE
How to do this in PIG and Hive

select concat (t1.col, t2.col)
from t t1 cross join t t2
where t1.col < t2.col
+----+
| AB |
| AC |
| AD |
| AE |
| BC |
| BD |
| BE |
| CD |
| CE |
| DE |
+----+

Related

UNION ALL not performing as expected - Oracle SQL

I have two tables:
tableA
| Part | Val |
|:----:|:---:|
| AA | 3 |
| AB | 2 |
| AC | 11 |
| AD | 6 |
| AE | 3 |
tableB
| Part | Val |
|:----:|:---:|
| AC | 9 |
| AF | 5 |
| AG | 1 |
| AH | 10 |
| AI | 97 |
I would like to union these tables to achieve this result:
| Part | ValA | ValB |
|:----:|:----:|:----:|
| AA | 3 | 0 |
| AB | 2 | 0 |
| AC | 11 | 9 |
| AD | 6 | 0 |
| AE | 3 | 0 |
| AF | 0 | 5 |
| AG | 0 | 1 |
| AH | 0 | 10 |
| AI | 0 | 97 |
I have tried:
SELECT * FROM tableA
UNION ALL
SELECT * FROM tableB
But that results in only one column of vals, which I do not want.
How can I merge these tables and create two columns, one for each table, where if the part does not appear in the other table, its value can just be 0?
SQL FIDDLE for reference.
It appears that you want to join the tables, not union them
select nvl(a.Part, b.Part) as Part,
nvl( a.Val, 0 ) as ValA,
nvl( b.Val, 0 ) as ValB
from tableA a
full outer join tableB b
on( a.Part = b.Part )
order by 1
Note that using case-sensitive identifiers like you do in your fiddle is generally frowned upon. It tends to make writing queries more complicated than it needs to be and it tends to get annoying to have to include the double quotes around every column name.
Demo
You can try below -
select part,max(valA),max(valB) from
(
select part, val as valA, 0 as valB from tableA
union all
select part, 0 , val from tableB
)A group by part

SQL - Fetch associated data from multiple table

I have 4 tables. The table does not contain any foreign key reference
t1:
| id | name |
+-----+----------------+
| a1 | cheese |
| a2 | butter |
| a3 | milk |
t2:
| id | name | t1_id |
+-----+-------------+--------------+
| b1 | item1 | a1 |
| b2 | item2 | a2 |
| b3 | item3 | a3 |
t3:
| id | name | t2_id |
+-----+-------------+--------------+
| c1 | item4 | b1 |
| c2 | item5 | b2 |
| c3 | item6 | b3 |
t4:
| id | name | t3_id |
+-----+-------------+--------------+
| d1 | item7 | c2 |
| d2 | item8 | c3 |
I need to get all associated data.
When I specify 'a1' I expect something as,
| name | name | name | name |
+----------+-------------+--------------+--------------+
| cheese | item1 |item4 | |
I used the following query,
SELECT a.name, b.name, c.name, d.name FROM t1 AS a
INNER JOIN t2 AS b ON b.id = c.id
INNER JOIN t3 AS c ON c.id = b.id
INNER JOIN t4 AS d ON d.id = c.id;
This fetches no result as INNER JOIN t4 AS d ON d.id = c.id does not have matching value.
How to return the intermediate result? Is this query optimized (or) should I write separate queries to fetch this? How to achieve this?
Do you just want left joins?
SELECT a.name, b.name, c.name, d.name
FROM t1 AS a LEFT JOIN
t2 AS b
ON b.id = c.id LEFT JOIN
t3 AS c
ON c.id = b.id LEFT JOIN
t4 AS d
ON d.id = c.id;

Unmatched rows with values from both tables

I have two tables T1:
+----+-----+--------------------+----------+
| ID | emp | manager | proj |
+----+-----+--------------------+----------+
| 1 | Sam | Tom | aa |
| 1 | Sam | Tom | bb |
| 1 | Sam | Tom | cc |
| 1 | Sam | Tom | dd |
+----+-----+--------------------+----------+
Table T2:
+--------+---------+--------+-----------+
| Course | Type | proj | Category |
+--------+---------+--------+-----------+
| XYZ | NEW | aa | a |
| DWE | OLD | bb | b |
| RTY | OLD | ii | c |
| UIO | NEW | gg | d |
+--------+---------+--------+-----------+
OUTPUT:
+-----------+-----+----------+--------+---------+---------+----------+
| ID | emp | manager | proj | Course | Type | Category |
+-----------+-----+----------+--------+---------+---------+----------+
| 1 | Sam | Tom | ii | RTY | OLD | c |
| 1 | Sam | Tom | gg | UIO | NEW | d |
+-----------+-----+----------+--------+---------+---------+----------+
I have one common col proj, table 1 has the proj done by the emp, table2 has both proj done and not done by emp with additional fields. I want to get all the unmatched rows from table2 but with the attributes from table 1 as above. Can someone help with a SQL query to do this??
Try this
with a as (
select T2.* from T1 right join T2
on T1.proj=T2.proj
where T1.proj is null) ,
b as (select T1.id, T1.emp, t1.manager from T1 left join T2
on T1.proj=T2.proj
group by T1.id, T1.emp, t1.manager,T2.proj
having T2.proj is null)
select * from a cross join b
select e.ID, e.emp, e.manager, t2.proj, t2.Course, t2.Type as Name, t2.Category
from t2
cross join (select distinct ID, emp, manager from T1) e
where not exists(select * from t1 where t1.prog=t2.proj)
SELECT tbl.ID, tbl.emp, tbl.manager, t2.proj, t2.Course, t2.Type as Name, t2.Category
FROM
(
SELECT t2.ID, t2.emp, t2.manager
FROM Table2 t2
WHERE NOT EXISTS (SELECT 1 FROM Table1 t1 WHERE t1.proj = t2.proj)
) tbl
CROSS APPLY Table1 t1

SQL conditional join to multiple tables in one shot

I would like to make conditional join of three tables. Left join table B and if the key is missing then join to table C.
+------+--+------+-------------+--+------+-------------+
| A.id | | B.id | B.OtherFish | | C.id | C.OtherFish |
+------+--+------+-------------+--+------+-------------+
| 1 | | 1 | B1 | | 1 | C1 |
| 2 | | | | | 2 | C2 |
| 3 | | 3 | B3 | | 3 | C3 |
| 4 | | | | | 4 | C4 |
| 5 | | 5 | B5 | | | |
| 6 | | 6 | B6 | | 6 | C6 |
+------+--+------+-------------+--+------+-------------+
There are no matching keys for 2 and 4 in B, and no keys for 5 in C.
Expected results:
+------+-----------+
| A.id | OtherFish |
+------+-----------+
| 1 | B1 |
| 2 | C2 |
| 3 | B3 |
| 4 | C4 |
| 5 | B5 |
| 6 | B6 |
+------+-----------+
The query I use is:
select
A.id
,coalesce(B.id,C.id)
,coalesce(B.OtherFish,C.OtherFish)
from A
left join B
on A.id=B.id
left join C
on A.id=C.id
The drawback of the approach is that I have to use coalesce through all the columns I need from different tables. It is annoying if there are hundred columns in the table. It would be desirable to make a coalesce on the whole aliases like coalesce(B,C).
Is it possible to make it in one shot like:
left join B
on A.id=B.id
left join C
on A.id=(case when B.id is null then C.id end)
so that in C.id I would have all good data without making coalesce through all the columns?
Although I don't see anything wrong with COALESCE , you can try using UNION , something like this:
SELECT a.id,t.OtherFish
FROM A
LEFT JOIN(SELECT b.id,b.otherFish FROM b
UNION ALL
SELECT c.id,c.otherFish FROM C
where c.id NOT EXISTS(SELECT 1 FROM b bb WHERE bb.id = c.id)) t
ON(a.id = t.id)

comparing rows in same table

I am having a result from a query which looks as below
+-------------------+
| id | c1 | c2 | c3 |
+-------------------+
| 1 | x | y | z |
+----+----+----+----+
| 1 | x | y | z1 |
+----+----+----+----+
| 2 | a | b | c |
+----+----+----+----+
| 2 | a1 | b | c1 |
+-------------------+
I need to fetch only records which have values in C1 and c2 different for the same id.
For the above example the result should be
+-------------------+
| id | c1 | c2 | c3 |
+-------------------+
| 2 | a | b | c |
+----+----+----+----+
| 2 | a1 | b | c1 |
+-------------------+
Can you please help with the query.
Joining the table to itself should work. I'm assuming that you meant C1 or C2 being different, given the example result you posted.
SELECT
t1.id,
t1.c1,
t1.c2,
t1.c3
FROM
your_table t1
INNER JOIN your_table t2 ON t1.id = t2.id
WHERE
t1.c1 <> t2.c1 OR
t1.c2 <> t2.c2
SQLFiddle.
This will give you any row which is different of any other. However in the case you have 3 rows, it might not work as you want.
SELECT t1.*
FROM someTable t1, someTable t2
WHERE t1.id = t2.id
AND (t1.c1 != t2.c1 OR t1.c2 != t2.c2)
Edit:
If you want only rows that are different of any other row with the same id the first query won't work in this case:
+-------------------+
| id | c1 | c2 | c3 |
+-------------------+
| 1 | x | y | z |
+----+----+----+----+
| 1 | x | y | z1 |
+----+----+----+----+
| 2 | a | b | c |
+----+----+----+----+
| 2 | a1 | b | c1 |
+----+----+----+----+
| 2 | a1 | b | c3 |
+-------------------+
You would get:
+-------------------+
| id | c1 | c2 | c3 |
+-------------------+
| 2 | a | b | c |
+----+----+----+----+
| 2 | a1 | b | c1 |
+----+----+----+----+
| 2 | a1 | b | c3 |
+-------------------+
Which I think would be wrong. In that case you will need something like:
SELECT t2.*
FROM
(
SELECT id, c1, c2
FROM someTable
GROUP BY id, c1, c2
HAVING COUNT(*) = 1
) t1
JOIN someTable t2 ON t2.id = t1.id
AND t2.c1 = t1.c1
AND t2.c2 = t1.c2
If I understood the question correctly I think the answer of #MattGibson is correct, but if the order matters then order by clause will be required (order by id).
Try this:
SELECT * FROM myTable WHERE ID
IN(SELECT ID FROM myTable GROUP BY ID HAVING COUNT(ID)>1)