Get name from two ids by joining tables (SQL) - sql

First table
MEMO_ID1
MEMO_ID2
UPDATED_BY
1
2
Bob
Second table
MEMO_ID1
MEMO_NAME
1
UD
2
LD
Result table I want:
MEMO_ID1
MEMO_ID2
UPDATED_BY
UD
LD
Bob
SELECT u.MEMO_ID1, u.MEMO_ID2, u.UPDATED_BY
FROM USER u;
How can I join the user and memo tables to get the names of two different IDs?

try with below:
select t2.MEMO_ID1,t2.MEMO_NAME,t11.UPDATED_BY
from table2 t2
join table1 t11 on t2.MEMO_ID1=t11.MEMO_ID1
join table1 t12 on t2.MEMO_ID1=t12.MEMO_ID2
where t11.UPDATED_BY=t12.UPDATED_BY

You didn't mentioned a database engine you're using so I will do all the stuff with T-SQL. Other DB engines have its own functions for pivoting data
In order to join data from table1 with table2 you need to pivot table1.
For pivoting this data you have 2 ways:
one option is using UNPIVOT
SELECT updated_by, pvt_id
FROM (
SELECT memo_id1, memo_id2, updated_by
FROM t1
) pvt
UNPIVOT (pvt_id FOR col_names IN (memo_id1, memo_id2)) AS unpvt
and another one is UNION data like that
SELECT memo_id1, updated_by
FROM t1
UNION
SELECT memo_id2, updated_by
FROM t1
Now you can join this data with table2 and pivot result back
WITH source AS
(
SELECT updated_by, pvt_id
FROM
(
SELECT memo_id1
,memo_id2
,updated_by
FROM t1
) pvt UNPIVOT (pvt_id FOR col_names IN (memo_id1, memo_id2)) AS unpvt
),
r1 AS
(
SELECT *
FROM source s
LEFT JOIN t2
ON t2.memo_id = s.pvt_id
)
SELECT updated_by, [1] AS [memo1], [2] AS [memo2]
FROM
(
SELECT updated_by, memo_name, memo_id
FROM r1
) pvt
PIVOT (MIN(memo_name) for memo_id IN ([1] , [2])) AS pvt2;
or the same with UNION and PIVOT
WITH source (m_id, updated_by) AS
(
SELECT memo_id1, updated_by
FROM t1 union
SELECT memo_id2, updated_by
FROM t1
),
r1 AS
(
SELECT *
FROM source
LEFT JOIN t2
ON t2.memo_id = t1_data.m_id
)
SELECT updated_by,[1] AS [memo1],[2] AS [memo2]
FROM
(
SELECT updated_by, memo_name, memo_id
FROM r1
) pvt
PIVOT (MIN(memo_name) for memo_id IN ([1], [2])) AS pvt2;
Even a bit simpler solution if you really need to solution on the data of your example without extensibility
with source (m_id, updated_by) as (
select memo_id1, updated_by
from t1
union
select memo_id2, updated_by
from t1
)
select s.updated_by, min(t2.memo_name) [memo1], max(t2.memo_name) [memo2]
from source s
LEFT JOIN t2 on t2.memo_id = s.m_id
group BY s.updated_by
;

Related

How to convert Oracle SQL query into datalake(Impala)?

I have one Oracle SQL query in the below format how I can proceed to convert this into Impala:-
SELECT
Some_Columns
FROM
(
SELECT * FROM
(
SELECT
Some_more_columns
FROM
Main_table
LEFT JOIN t1 on codn_1 = cond_2
....
....
Some more left joins
.....
WHERE
some_filters
)
PIVOT(
count(*) for column_x in (some_column)
)
) T
ORDER BY 2,3

Unpivot without using columns names

Right now my query is resulting data in below format.
dbid askid amid
================================
d1 m1 a1
I want to change the display as
SOURCE_ID DEST_ID
========================
m1 d1
a1 d1
We can't use union all, inner joins, cross joins because in real time it is very big query and interacts with n no.of multiple tables and it already have them many no.of
I tried using unpivot but every time it is storing column names also in to rows.
Sample Query which is resulting data right now:
select DEST_ID,SOURCE_ID from
(select
t1.id as dbid,
t2.mid as askid,
t3.m2idd as amid from
table1 t1, table2 t2, table3 t3 where
t1.actid = t2.senid
and t2.denid = t2.mkid
)
unpivot INCLUDE NULLS (SOURCE_ME_GUID FOR DEST_ME_GUID IN (amid, askid));
Use UNION ALL in combination with a WITH clause.
You got confused with your join criteria somehow. I suppose either mkid or denid resides in table3. Otherwise you'd be cross joining table3. You shouldn't use this 1980s join syntax anyway; it's been made redundant in 1992 for a reason.
with ids as
(
select t1.id as dbid, t2.mid as askid, t3.m2idd as amid
from table1 t1
join table2 t2 on t2.senid = t1.actid
join table3 t3 on t3.mkid = t2.denid
)
select askid as source_id, dbid as dest_id from ids
union all
select amid as source_id, dbid as dest_id from ids;
Solution for the above issue.
select dbid as DEST_ID, SOURCE_ID
from (
select 'd1' dbid,
cast('m1' as varchar2(200)) as askid,
cast('a1' as varchar2(200)) as amid
from dual
) unpivot INCLUDE NULLS (
SOURCE_ID FOR DEST_ID IN (amid, askid)
);

missing rows, how to select values

How to accomplish this: I have bunch of numbers (for example: 2342423; 34443123; 3523423) and some of them are in my database table as primary key value. I want to select only those numbers, which are not in my table. What is the best way to do this?
If it is just a few numbers you can do
select tmp.num
from
(
select 2342423 as num
union all
select 34443123
union all
select 3523423
) tmp
left join your_table t on t.id = tmp.num
where t.id is null
If it is more than a few numbers you should insert these into a table and left join against that table like this
select twntc.num
from table_with_numbers_to_check twntc
left join your_table t on t.id = twntc.num
where t.id is null

Logical AND between table elements in T-SQL

I have n tables all with the same fields: Username and Value. The same Username can have multiple registers on each table but the combination Username/Value is unique on each one.
I want to join the tables into a single one which contains all the users who appear on all the tables with all the different (Username/Value) pairs.
Example
Table A: {(User1,Value1);(User1,Value2);(User2,Value2);(User3,Value4)]
Table B: {(User1,Value4);(User3,Value5)]
Table C: {(User1,Value5);(User1,Value2);(User2,Value7);(User3,Value8)]
Desired output
Table D: {(User1,Value1);(User1,Value2);(User1,Value4);(User1,Value5);(User3,Value4);(User3,Value5);(User3,Value8)}
Now I'm doing multiple joins (using perl) like this
SELECT *
INTO $target_table
FROM (SELECT *
FROM $table1
WHERE bname IN (SELECT DISTINCT bname FROM $table2)
UNION
SELECT *
FROM $table2
WHERE bname IN (SELECT DISTINCT bname FROM $table1)
) UN
and then doing the same join between a third table and target_table and so on, but I think it should be a better way.
Any hints?
You can use UNION for this:
SELECT username, value
FROM $table1
UNION
SELECT username, value
FROM $table2
...
SELECT username, value
FROM $tablex
SQL Fiddle Demo
This will return you distinct records. If you are interested in duplicates, use UNION ALL.
Given your edits, it appears you only want to return records if the user is in all the tables.
Breaking that down, you need to do a few things. First, combine all your records together again, but this time denote which table each are coming from. Then you need to know the count of tables each user is in. Finally you need to check that number against the overall number of tables.
Here's one way using a few CTEs:
WITH CTE AS (
SELECT username, value, 1 AS tbl
FROM t1
UNION
SELECT username, value, 2 AS tbl
FROM t2
UNION
SELECT username, value, 3 AS tbl
FROM t3
),
CTECnt AS (
SELECT username, COUNT(DISTINCT tbl) tblCnt
FROM CTE
GROUP BY username
),
CTEMaxCnt AS (
SELECT COUNT(DISTINCT tbl) MaxCnt
FROM CTE
)
SELECT C.username, C.value
FROM CTE C
JOIN CTECnt C2 ON C.username = C2.username
JOIN CTEMaxCnt C3 ON C2.tblCnt = C3.MaxCnt
Another SQL Fiddle Demo
With Combined As
(
Select 'A' As TableName, Username, Value
From TableA
Union All
Select 'B', Username, Value
From TableB
Union All
Select 'C', Username, Value
From TableC
)
Select C.Username, C.Value
From Combined As C
Join (
Select C1.Username
From Combined As C1
Group By C1.Username
Having Count(Distinct C1.TableName) = 3
) As Z
On Z.Username = C.Username
Group By C.Username, C.Value
SQL Fiddle version

SQL Select Distinct with Conditional

Table1 has columns (id, a, b, c, group). There are several rows that have the same group, but id is always unique. I would like to SELECT group,a,b FROM Table1 WHERE the group is distinct. However, I would like the returned data to be from the row with the greatest id for that group.
Thus, if we have the rows
(id=10, a=6, b=40, c=3, group=14)
(id=5, a=21, b=45, c=31, group=230)
(id=4, a=42, b=65, c=2, group=230)
I would like to return these 2 rows:
[group=14, a=6,b=40] and
[group=230, a=21,b=45] (because id=5 > id=4)
Is there a simple SELECT statement to do this?
Try:
select grp, a, b
from table1 where id in
(select max(id) from table1 group by grp)
You can do it using a self join or an inner-select. Here's inner select:
select `group`, a, b from Table1 AS T1
where id=(select max(id) from Table1 AS T2 where T1.`group` = T2.`group`)
And self-join method:
select T1.`group`, T2.a, T2.b from
(select max(id) as id,`group` from Table1 group by `group`) T1
join Table1 as T2 on T1.id=T2.id
2 selects, your inner select gets:
SELECT MAX(id) FROM YourTable GROUP BY [GROUP]
Your outer select joins to this table.
Think about it logically, the inner select gets a sub set of the data you need.
The outer select inner joins to this subset and can get further data.
SELECT [group], a, b FROM YourTable INNER JOIN
(SELECT MAX(id) FROM YourTable GROUP BY [GROUP]) t
ON t.id = YourTable.id
SELECT mi.*
FROM (
SELECT DISTINCT grouper
FROM mytable
) md
JOIN mytable mi
ON mi.id =
(
SELECT id
FROM mytable mo
WHERE mo.grouper = md.grouper
ORDER BY
id DESC
LIMIT 1
)
If your table is MyISAM or id is not a PRIMARY KEY, then make sure you have a composite index on (grouper, id).
If your table is InnoDB and id is a PRIMARY KEY, then a simple index on grouper will suffice (id, being a PRIMARY KEY, will be implictly included).
This will use an INDEX FOR GROUP-BY to build the list of distinct groupers, and for each grouper it will use the index access to find the maximal id.
Don't know how to do it in mysql. But the following code will work for MsSQL...
SELECT Y.* FROM
(
SELECT DISTINCT [group], MAX(id) ID
FROM Table1
GROUP BY [group]
) X
INNER JOIN Table1 Y ON X.ID=Table1.ID