SQL interview questions - sql

Table-1
Col1 col2
11 A
26 B
31 C
43 D
Table-2
Col1 col2
16 E
46 F
39 G
42 H
And need output is
Col1 col2 Col1 col2
11 A 16 E
26 B 46 F
31 C 39 G
43 D 42 H

Here's one option:
SQL> with
2 -- sample data
3 a (col1, col2) as
4 (select 11, 'A' from dual union all
5 select 26, 'B' from dual union all
6 select 31, 'C' from dual union all
7 select 43, 'D' from dual
8 ),
9 b (col1, col2) as
10 (select 16, 'E' from dual union all
11 select 46, 'F' from dual union all
12 select 39, 'G' from dual union all
13 select 42, 'H' from dual
14 ),
15 -- find something to join rows on - for example, row number. Your example shows that
16 -- values are sorted by COL2
17 a2 as
18 (select col1, col2, row_number() over (order by col2) rn from a),
19 b2 as
20 (select col1, col2, row_number() over (order by col2) rn from b)
21 -- join a2 and b2 on RN
22 select a2.col1, a2.col2, b2.col1, b2.col2
23 from a2 join b2 on a2.rn = b2.rn
24 order by a2.col1;
COL1 COL2 COL1 COL2
----- ---- ----- ----
11 A 16 E
26 B 46 F
31 C 39 G
43 D 42 H
SQL>

select t1.col1, t1.col2, t2.col1, t2.col2 from table1 as t1
left join table2 as t2 on 1=1
Try this

select * from table1 t1 join table2 t2 on ascii(t1.col2)+4 = ascii(t2.col2);
Note: this only works with the specific input provided, but why not? It just goes to show that providing minimal input and expected output is not sufficient. You have to explain what rules the input should follow and what rules the processing should follow.
Littlefoot answers a different question than I do, but even he silently makes some assumptions. For example, he decided not to show any output if there are unmatched rows on one side or the other.
The correct real-world answer to this interview question would be to list the questions one would have to ask before being able to supply an appropriate answer.

Related

How can I select a data from another column from rows that have been selected?

I tried my best to figure and google this out, but couldn't really find a solid answer to it.
The problem I'm facing is that
Table 1:
ID Value 1
1 a
2 b
3 c
Table 2:
ID Value 2
1 4a
3 5b
4 6c
and I'd basically have to select the value from Table 1 that doesn't exist on Table 2 (Thus, 'b')
I can select and identify the ID that I want by using minus function between the tables, but can't seem to figure out a way to call a query to instead call the data.
Use the MINUS as a subquery (i.e. an inline view) (lines #14 - 16):
Sample data:
SQL> with
2 table1(id, value1) as
3 (select 1, 'a' from dual union all
4 select 2, 'b' from dual union all
5 select 3, 'c' from dual
6 ),
7 table2 (id, value2) as
8 (select 1, '4a' from dual union all
9 select 3, '5b' from dual union all
10 select 4, '6c' from dual
11 )
Query begins here:
12 select a.*
13 from table1 a
14 where a.id in (select t1.id from table1 t1
15 minus
16 select t2.id from table2 t2
17 );
ID VALUE1
---------- ----------
2 b
SQL>
Alternatively, use not exists:
<snip>
12 select a.*
13 from table1 a
14 where not exists (select null
15 from table2 b
16 where b.id = a.id
17 );
ID VALUE1
---------- ----------
2 b
SQL>

input table 1 (5 6 7) (Five Six Seven) and table 2 (5 6 7 ). Both in brackets are columns with values.,I want to get the five for the 5 in table2

table 1
col1
col2
5
five
6
six
8
eight
table 2
5|6|5
6|5
8|8|5
Expected output
|five|six|five|
|six|five|
|eight|eight|five|
That "link" you're talking about is called a join.
As you put it, that would be as follows:
Sample data (you already have that and don't type it):
SQL> with
2 table_1 (col1, col2) as
3 (select 5, 'five' from dual union all
4 select 6, 'six' from dual union all
5 select 8, 'eight' from dual
6 ),
7 table_2 (col1) as
8 (select 5 from dual union all
9 select 6 from dual union all
10 select 8 from dual
11 )
12 --
Query begins here:
13 select b.col1
14 from table_1 a join table_2 b on a.col1 = b.col1
15 where a.col2 = '&par_col2';
Enter value for par_col2: five
COL1
----------
5
SQL> /
Enter value for par_col2: eight
COL1
----------
8
SQL>
Depending on a tool you use, where clause might use a bind variable instead of a substitution one (I used in SQL*Plus), i.e.
where a.col2 = :par_col2
On the other hand, what do you need table_2 for? Everything you need is contained in table_1, so query would then be just
<snip>
13 select a.col1
14 from table_1 a
15 where a.col2 = '&par_col2';
Enter value for par_col2: six
COL1
----------
6
SQL>

How to convert rows into columns in oracle into particular set of columns?

I have a table in which there are 2 columns. I want to convert the rows into sets of 4 columns.
For example, the table I have:
Column1
Column2
1
N
2
N
3
N
4
N
5
N
I want to transpose them as:
Column1
Columnn2
Column3
Column4
1
2
3
4
5
N
N
N
N
N
How can I do this in Oracle?
Thanks for the help!
Here's one option; read comments within code.
SQL> with
2 test (col1, col2) as
3 -- sample data
4 (select 1, 'N' from dual union all
5 select 2, 'N' from dual union all
6 select 3, 'N' from dual union all
7 select 4, 'N' from dual union all
8 select 5, 'N' from dual
9 ),
10 temp as
11 -- union of two columns will produce a single-column "table"
12 (select to_char(col1) col from test union all
13 select col2 from test
14 ),
15 temp2 as
16 -- ordinal numbers for each row
17 (select col,
18 row_number() over (order by null) rn
19 from temp
20 ),
21 temp3 as
22 -- a little bit of calculation so that you'd be able to create groups of 4 columns
23 (select col,
24 mod(rn, 4) rn,
25 ceil(rn / 4) grp
26 from temp2
27 )
28 -- final query
29 select max(case when rn = 1 then col end) col1,
30 max(case when rn = 2 then col end) col2,
31 max(case when rn = 3 then col end) col3,
32 max(case when rn = 0 then col end) col4
33 from temp3
34 group by grp;
COL1 COL2 COL3 COL4
----- ----- ----- -----
1 2 3 4
5 N N N
N N
SQL>

Sql Query for Unique and Duplicates in oracle sql?

I need to display unique records in one column and duplicates in another column in Oracle?
COL1 COL2
1 10
1 10
2 20
3 30
3 30
unique in one set duplicate in one set
col1 col2 col1 col2
2 20 1 10
1 10
3 30
3 30
You can use the group by for both cases with the having clause:
Unique records
select *
from table as t
inner join (
select col1, col2, count(*) as times
from table
group by col1, col2
having count(*) = 1) as t2 ON t.col1 = t2.col2 and t.col2 = t2.col2
Duplicate records:
select *
from table as t
inner join (
select col1, col2, count(*) as times
from table
group by col1, col2
having count(*) > 1) as t2 ON t.col1 = t2.col1 and t.col2 = t2.col2
Would something like this do? See comments within code.
SQL> with
2 test (col1, col2) as
3 -- sample data
4 (select 1, 10 from dual union all
5 select 1, 10 from dual union all
6 select 2, 20 from dual union all
7 select 3, 30 from dual union all
8 select 3, 30 from dual
9 ),
10 uni as
11 -- unique values
12 (select col1, col2
13 from test
14 group by col1, col2
15 having count(*) = 1
16 ),
17 dup as
18 -- duplicate values
19 (select col1, col2
20 from test
21 group by col1, col2
22 having count(*) > 1
23 )
24 -- the final result
25 select u.col1 ucol1,
26 u.col2 ucol2,
27 d.col1 dcol1,
28 d.col2 dcol2
29 from uni u full outer join dup d on u.col1 = d.col1;
UCOL1 UCOL2 DCOL1 DCOL2
---------- ---------- ---------- ----------
1 10
3 30
2 20
SQL>
You can identify the duplicate values using window functions, and then filter each query. Then to get unique records:
select col1, col2
from (select t.*, count(*) over (partition by col1) as cnt
from t
) t
where cnt = 1;
To get duplicates:
select col1, col2
from (select t.*, count(*) over (partition by col1) as cnt
from t
) t
where cnt > 1;

PLSQL - Compare two comma separated and remove duplicate

I have comma separated values in two column and i wants to remove "common" values available in both column. Below is the sample data
col1 col2
1234, 5623, 1236,1567 5623, 9089,1567,2890,1234
145,126,1236,1478 1748,8956,1234,1478
Required Data
COL1 COL2
1236 9089,2890
145,126,1236 1748,8956,1234
Thanks
I've slightly modified your table and added the ID column which uniquely identifies a row, so it looks like this:
SQL> select * from test;
ID COL1 COL2
---------- ------------------------------ ------------------------------
1 1234, 5623, 1236,1567 5623, 9089,1567,2890,1234
2 145,126,1236,1478 1748,8956,1234,1478
This approach
splits all columns into rows (t_one is for col1, t_two is for col2)
inter CTE uses the INTERSECT set operator in order to find common values which should be removed from the result
t1_new and t2_new aggregate new column values (using the LISTAGG function)
the final SELECT returns the final result
Here it goes:
SQL> with
2 t_one as
3 (select id,
4 trim(regexp_substr(col1, '[^,]+', 1, column_value)) c1
5 from test,
6 table(cast(multiset(select level from dual
7 connect by level <= regexp_count(col1, ',') + 1
8 ) as sys.odcinumberlist))
9 ),
10 t_two as
11 (select id,
12 trim(regexp_substr(col2, '[^,]+', 1, column_value)) c2
13 from test,
14 table(cast(multiset(select level from dual
15 connect by level <= regexp_count(col2, ',') + 1
16 ) as sys.odcinumberlist))
17 ),
18 inter as
19 (select t1.id, t1.c1 cx from t_one t1
20 intersect
21 select t2.id, t2.c2 cx from t_two t2
22 ),
23 t1_new as
24 (select a.id, listagg(a.c1, ',') within group (order by a.c1) c1_new
25 from (select t1.id, t1.c1 from t_one t1
26 minus
27 select i.id, i.cx from inter i
28 ) a
29 group by a.id
30 ),
31 t2_new as
32 (select b.id, listagg(b.c2, ',') within group (order by b.c2) c2_new
33 from (select t2.id, t2.c2 from t_two t2
34 minus
35 select i.id, i.cx from inter i
36 ) b
37 group by b.id
38 )
39 select a.id, a.c1_new, b.c2_new
40 from t1_new a join t2_new b on a.id = b.id;
ID C1_NEW C2_NEW
---------- -------------------- --------------------
1 1236 2890,9089
2 1236,126,145 1234,1748,8956
SQL>