sql query to get the column data in one row - oracle

I have below data in a table called data_tab
sn code
2 101
2
2 202
5 103
5
5
How can i query to see result in one row, like
sn code1 code2 code3
2 101 202
5 103

Hi This gives the intented output ... take a look here
select sn,
max(decode(rn,1,code)) as CODE_1
,max(decode(rn,2,code)) as CODE_2
,max(decode(rn,3,code)) as CODE_3
from
(
select sn,
code,
row_number() over (partition by sn order by null ) rn
from test
)
group by sn

Related

Query to find before and after values of a given value

If we have table Employees
EMP_ID ENAME SALARY DEPT_ID
1 abc 1000 10
2 bca 1050 10
3 dsa 2000 20
4 zxc 3000 30
5 bnm 5000 30
6 rty 5050 30
I want to get the rank of the salary with before 2 values and after 2 values including the given rank
Like if I give rank 4 it should give ranks 2,3,4,5,6 details.
output should be
5 bnm 5000 30
4 zxc 3000 30
3 dsa 2000 20
3 dsa 2000 20
2 bca 1050 10
1 abc 1000 10
I have a query
WITH dept_count AS (
SELECT
e.*,
dense_rank() over( ORDER BY salary DESC) AS rk
FROM employees e
)
SELECT
*
FROM dept_count dc
WHERE dc.rk BETWEEN (
SELECT
c.rk-2
FROM dept_count c
WHERE c.rk =4
)
AND (
SELECT
c.rk + 2
FROM dept_count c
WHERE c.rk = 4
)
but I need a query which can be simplified.
Could someone help me with this query?
You just need to use ROW_NUMBER() along with a substitution parameter :
WITH dept_count AS (
SELECT
e.*,
ROW_NUMBER() OVER( ORDER BY salary DESC) AS rk
FROM employees e
)
SELECT *
FROM dept_count
WHERE rk BETWEEN &prm - 2 AND &prm + 2

write function which will display train details having maximum passanger for given date?

following are the table in database.
many to many relations between train and passenger
table 1 name=train
TNO TNAMe
1 x
2 y
3 z
table 2 name=passenger
PNO PNAME
111 a
222 b
333 c
table 3 name=tp
TNO PNO TPDATE
1 111 23-NOV-15
2 222 24-JUN-14
3 222 19-JUN-13
1 333 23-NOV-15
using follwing code i only find out which train number has highest frequency
select tno,count(tno) as numberofoccurance from tp group by tno
Try to use group by and row_number analytical function as following:
Select name, tp_date
From
(Select t.tname tp.tp_date,
row_number() over (partition by tp.tp_date order by count(1) desc nulls last) as cnt
From train t
Join tp tp
On (t.id = tp.tno)
Group by tp.tno, tp.tp_date)
Where cnt = 1;
Cheers!!

Order column inside PIVOT on the basis of max(count_date) for each value inside in condition

I have users name in column users, I want to display all users as a column and the order of representation of column must be in descending order of their sum of data.
query:
select *
from (
select sum(tran_count) over (partition by schema) as table_name
from main_table
) pivot (sum(tran_count) for users in ('abc','lmn','pqr'));
ans:
schema table abc lmn pqr
pm sector 32 216 12
history trn 321 61 4
tap issuer 43 325 2
count: 396 602 18
so I want to represent the column abc,lmn and pqr in order of count of their data:
required answer:
schema table lmn abc pqr
pm sector 216 32 12
history trn 61 321 4
tap issuer 325 43 2
You cannot use (sub)query in pivot's in clause. What you can do is to rank users according to their summaric values and use these three values (1, 2, 3) in in. Then either use my inner query, which presents user names and sums in separate columns or make a final union, where names are listed in first row and sums in rows below as strings.
with t as (
select *
from (
select dense_rank() over (order by smu desc, users) rn,
schema_, table_, users, smt
from (
select schema_, table_, users, sum(tran_count) smt,
sum(sum(tran_count)) over (partition by users) smu
from main_table
group by schema_, table_, users))
pivot (max(users) name, max(smt) smt for rn in (1 u1, 2 u2, 3 u3)))
select null schema_, null table_, u1_name u1, u2_name u2, u3_name u3
from t where rownum = 1 union all
select schema_, table_, to_char(u1_smt), to_char(u2_smt), to_char(u3_smt)
from t
dbfiddle demo
If you really need to put user names in headers then you have to use dynamic SQL or external code-writing-code technique.
I don't know if you really have columns like table or schema, these are reserved words, also once you write tran_count and in title count_date, so I am somewhat confused. But you can see in the linked dbfiddle working example with columns schema_, table_, users, tran_count.

Convert rows to columns like pivot

I have a data like:
formid formownerid approverid
1 100 102
1 100 103
1 100 104
2 200 107
2 200 103
2 200 109
2 200 105
3 400 201
3 400 210
I want to convert it to:
formid formownerid approverid approverid approverid approverid
1 100 102 103 104 NULL
2 200 107 103 109 105
3 400 201 202 NULL NULL
Wherever I looked at I saw pivot/unpivot but it looks unrelated since we don't need aggregation.
The aggregate is a necessary part of the pivot, but it's simple to apply here; you don't want sum but a max aggregate works fine:
select *
from (
select t.*,
row_number() over (partition by formid, formownerid
order by approverid) as rn
from t42 t
)
pivot (max(approverid) as approverid for (rn) in (1, 2, 3, 4));
FORMID FORMOWNERID 1_APPROVERID 2_APPROVERID 3_APPROVERID 4_APPROVERID
---------- ----------- ------------ ------------ ------------ ------------
1 100 102 103 104
2 200 103 105 107 109
3 400 201 210
Or you can specify the column name prefix explicitly to make them valid identifiers:
pivot (max(approverid) as approverid
for (rn) in (1 as a, 2 as b, 3 as c, 4 as d));
The inner query is adding a pseudocolumn rn to the table results to give you a fixed value to pivot against, since the actual approver IDs aren't going to be known in advance.
The manual approach might make this a bit clearer:
select formid, formownerid,
max(case when rn = 1 then approverid end) as approverid_1,
max(case when rn = 2 then approverid end) as approverid_2,
max(case when rn = 3 then approverid end) as approverid_3,
max(case when rn = 4 then approverid end) as approverid_4
from (
select t.*,
row_number() over (partition by formid, formownerid
order by approverid) as rn
from t42 t
)
group by formid, formownerid
order by formid, formownerid;
FORMID FORMOWNERID APPROVERID_1 APPROVERID_2 APPROVERID_3 APPROVERID_4
---------- ----------- ------------ ------------ ------------ ------------
1 100 102 103 104
2 200 103 105 107 109
3 400 201 210
The inner query is the same. The case statement produces each column as above, but without the max and grouping you get multiple rows with lots of extra blanks:
select formid, formownerid,
case when rn = 1 then approverid end as approverid_1,
case when rn = 2 then approverid end as approverid_2,
case when rn = 3 then approverid end as approverid_3,
case when rn = 4 then approverid end as approverid_4
from (
select t.*,
row_number() over (partition by formid, formownerid
order by approverid) as rn
from t42 t
);
FORMID FORMOWNERID APPROVERID_1 APPROVERID_2 APPROVERID_3 APPROVERID_4
---------- ----------- ------------ ------------ ------------ ------------
1 100 102
1 100 103
1 100 104
2 200 103
2 200 105
2 200 107
2 200 109
3 400 201
3 400 210
Notice that there's only a value in (at most) one column for each formid/formownerid combination, but that they appear in different rows. The max suppresses those multiple rows; and the pivot version does something similar under the hood.
SQL Fiddle showing the manual approach with the intermediate step, and the pivot version.
One possible Approch:
SELECT FROMID, FROMOWNERID, APPROVERID, NULL APPROVERID, NULL APPROVERID, NULL APPROVERID
FROM yourtable
WHERE FROMID = 100
AND APPROVERID = 102
UNION ALL
SELECT FROMID, FROMOWNERID, NULL APPROVERID, APPROVERID APPROVERID, NULL APPROVERID, NULL APPROVERID
FROM yourtable
WHERE FROMID = 100
AND APPROVERID = 103
UNION ALL
SELECT FROMID, FROMOWNERID, NULL APPROVERID, NULL APPROVERID, APPROVERID APPROVERID, NULL APPROVERID
FROM yourtable
WHERE FROMID = 100
AND APPROVERID = 104
----
-------
And So On

Conversion from standard SQL to Oracle Syntax

I have a problem with converting a standard SQL join into the old Oracle join syntax (please don't ask me why I need that). I would expect the same result, anyway, it is not:
Sample Data:
create table testing (
aid number(8),
bid number(8),
btext varchar(80));
insert into testing values (100,1,'text1a');
insert into testing values (100,2,'text1b');
insert into testing values (100,3,'text1c');
insert into testing values (200,19,'text2b');
insert into testing values (200,18,'text2a');
insert into testing values (300,4324,'text3a');
insert into testing values (500,80,'text4a');
insert into testing values (50,2000,'text5a');
commit;
Standard SQL:
select a.*,b.* from testing a
left outer join testing b
on (a.aid = b.aid and a.bid < b.bid)
order by a.aid, b.bid;
AID BID BTEXT AID_1 BID_1 BTEXT_1
50 200 text5a NULL NULL NULL
100 1 text1a 100 2 text1b
100 2 text1b 100 3 text1c
100 1 text1a 100 3 text1c
100 3 text1c NULL NULL NULL
200 18 text2a 200 19 text2b
200 19 text2b NULL NULL NULL
300 432 text3a NULL NULL NULL
500 80 text4a NULL NULL NULL
Oracle SQL:
select a.*,b.* from testing a, testing b
where a.aid = b.aid(+)
and a.bid < b.bid
order by a.aid, b.bid;
AID BID BTEXT AID_1 BID_1 BTEXT_1
100 1 text1a 100 2 text1b
100 2 text1b 100 3 text1c
100 1 text1a 100 3 text1c
200 18 text2a 200 19 text2b
How to get the same result of the standart SQL using Oracle's legacy syntax?
Your Oracle-style statement needs the (+) operator also on the less-than condition, since that is also part of your join criteria in the standard-SQL version.
select a.*,b.* from testing a, testing b
where a.aid = b.aid(+)
and a.bid < b.bid(+)
order by a.aid, b.bid;
See sqlfiddle here.

Resources