looping and union all in oracle select statement - sql

I have the following table in oracle. version 9i
Num count
123 1
345 4
455 3
234 2
542 1
I am trying to write a select query which gives me the following output.
123
345
345
345
345
455
455
455
234
234
542
Each number should be displayed its count number of times. Can this be achieved if I use functions? I am not allowed to create any temporary tables.
I understand that I have to use loops sequences and then UNION ALL but not sure how to achieve it. I tried this
select Num from <table> where count=1
union all
// what fits here?

This could be done using pseudo column LEVEL and Correlated Query for repeating the num count number of times...
Try the below query
select num from (select distinct num,level,ROWID as RD
from table a
connect by level<= (select count from table b where a.num=b.num))
order by rd;

Try this
SELECT A.NUM
FROM Test A
INNER JOIN (SELECT ROWNUM RN FROM dual connect by level < 100) B
ON B.rn <= A.count
order by A.NUM;
SQL DEMO

WITH cte ("Num", "count")
AS
(
SELECT "Num", "count" FROM TableName
UNION ALL
SELECT "Num", "count" - 1 FROM cte WHERE "count" > 1
)
SELECT "Num"
FROM cte
ORDER BY "Num"
SQLFiddle Demo

If you're using 11gR2 you can do it like this:
with t(num, i) as
(
select num, count from tab1 union all
select num, i-1
from t
where i >1
)
select num from t
order by num;
Here is a sqlfiddle demo

Related

How do i select all columns, plus the result of the sum

I have this select:
"Select * from table" that return:
Id
Value
1
1
1
1
2
10
2
10
My goal is create a sum from each Value group by id like this:
Id
Value
Sum
1
1
2
1
1
2
2
10
20
2
10
20
I Have tried ways like:
SELECT Id,Value, (SELECT SUM(Value) FROM Table V2 WHERE V2.Id= V.Id GROUP BY IDRNC ) FROM Table v;
But the is not grouping by id.
Id
Value
Sum
1
1
1
1
1
1
2
10
10
2
10
10
Aggregation aggregates rows, reducing the number of records in the output. In this case you want to apply the result of a computation to each of your records, task carried out by the corresponding window function.
SELECT table.*, SUM(Value) OVER(PARTITION BY Id) AS sum_
FROM table
Check the demo here.
Your attempt looks correct.
Can you try the below query :
It works for me :
SELECT Id, Value,
(SELECT SUM(Value) FROM Table V2 WHERE V2.Id= V.Id GROUP BY ID) as sum
FROM Table v;
You can do it using inner join to join with selection grouped by id :
select t.*, sum
from _table t
inner join (
select id, sum(Value) as sum
from _table
group by id
) as s on s.id = t.id
You can check it here
Your select is ok if you adjust it just a little:
SELECT Id,Value, (SELECT SUM(Value) FROM Table V2 WHERE V2.Id= V.Id GROUP BY IDRNC ) FROM Table v;
GROUP BY IDRNC is a mistake and should be GROUP BY ID
you should give an alias to a sum column ...
subquery selecting the sum does not have to have self table alias to be compared with outer query that has one (this is not a mistake - works either way)
Test:
WITH
a_table (ID, VALUE) AS
(
Select 1, 1 From Dual Union All
Select 1, 1 From Dual Union All
Select 2, 10 From Dual Union All
Select 2, 10 From Dual
)
SELECT ID, VALUE, (SELECT SUM(VALUE) FROM a_table WHERE ID = v.ID GROUP BY ID) "ID_SUM" FROM a_table v;
ID VALUE ID_SUM
---------- ---------- ----------
1 1 2
1 1 2
2 10 20
2 10 20

rank a column with out ordering in oracle

I have the data as below, When I apply dense_rank by ordering id column, I am getting rank according to the order of integers but I need to rank as the records are displayed when run a query:
Data from query:
Rid id
8100 161
8101 2
8102 2
8103 2
8104 156
When I apply dense_rank over order by id then I am getting
Rid id rank
8100 161 3
8101 2 1
8102 2 1
8103 2 1
8104 156 2
But my requirement is to get in below way:
Rid id rank
8100 161 1
8101 2 2
8102 2 2
8103 2 2
8104 156 3
Used row_number as well but the result is not as expected, not sure what option would be the better way.
Any help is appreciated.
Thanks
Edit------------------------------
Query used
Select rid, id,dense_rank() over (order by id) row_num
from table
I have adjusted solution from here: DENSE_RANK according to particular order for your need.
I am not sure if I should mark this as duplicate because on this link above there is no ORACLE tag. If more experience members think I should please do comment and I will do so and delete this answer.
Here is the adjusted code and demo:
SELECT t2.rid
, t2.id
, DENSE_RANK() OVER (ORDER BY t2.max_rid)
FROM (
SELECT MAX(t1.rid) OVER (PARTITION BY t1.grupa) AS max_rid
, t1.rid
, t1.id
FROM (
SELECT rid
, id
,ROW_NUMBER() OVER (ORDER BY rid) - ROW_NUMBER() OVER (PARTITION BY id ORDER BY rid) AS grupa
FROM test_table) t1 ) t2
ORDER BY rid
DEMO
You can use sum() aggregation containing (order by rid) after getting the values from lag() analytic function within the first query
with tab( rid,id ) as
(
select 8100,161 from dual union all
select 8101,2 from dual union all
select 8102,2 from dual union all
select 8103,2 from dual union all
select 8104,156 from dual
), t2 as
(
select t.*, lag(id,1,0) over (order by rid) lg
from tab t
)
select rid, id, sum(case when lg!=id then 1 else 0 end) over (order by rid) as row_num
from t2
Demo

How to select max of two columns and group it by station on MS Access SQL

I have a simple table like this
station num tim
-------------------------
1 150 10
1 200 222
1 100 5000
1 200 555
2 100 500
2 120 200
3 1 2
The desired output is like this:
station num tim
---------------------
1 200 555
2 120 200
3 1 2
but I can't use ROW_NUMBER() because query needs to be executed in MS Access SQL.
Can anyone help me?
Try using subquery
select A.* from
(
select station,num, max(tim) as mtim
from tablename
group by station,num
)A where num in (select max(num) from tablename B where A.station=B.station)
You can try this also:
select t2.station,t1.num as num,max(t2.tim) tim from (select max(num) num
from tablename group by station) t1
join tablename on t1.num = t2.num group by t1.num,t2.station
You can do this with two exists queries:
select s.*
from simple as s
where s.num = (select max(s2.num)
from simple as s2
where s2.station = s.station
) and
s.tim = (select max(s2.tim)
from simple as s2
where s2.station = s.station and s2.num = s.num
) ;
Because this doesn't do aggregation (overall) and can make use of an index on (station, num, tim), it is probably the best performing approach.

SQL select columns group by

If I have a table which is of the following format:
ID NAME NUM TIMESTAMP BOOL
1 A 5 09:50 TRUE
1 B 6 13:01 TRUE
1 A 1 10:18 FALSE
2 A 3 12:20 FALSE
1 A 1 05:30 TRUE
1 A 12 06:00 TRUE
How can I get the ID, NAME and NUM for each unique ID, NAME pair with the latest Timestamp and BOOL=TRUE.
So for the above table the output should be:
ID NAME NUM
1 A 5
1 B 6
I tried using Group By but I cannot seem to get around that either I need to put an aggregator function around num (max, min will not work when applied to this example) or specifying it in group by (which will end up matching on ID, NAME, and NUM combined). Both as far as I can think will break in some case.
PS: I am using SQL Developer (that is the SQL developed by Oracle I think, sorry I am a newbie at this)
If you're using at least SQL-Server 2005 you can use the ROW_NUMBER function:
WITH CTE AS
(
SELECT ID, NAME, NUM,
RN = ROW_NUMBER()OVER(PARTITION BY ID, NAME ORDER BY TIMESTAMP DESC)
FROM Table
WHERE BOOL='TRUE'
)
SELECT ID, NAME, NUM FROM CTE
WHERE RN = 1
Result:
ID NAME NUM
1 A 5
1 B 6
Here's the fiddle: http://sqlfiddle.com/#!3/a1dc9/10/0
select t1.* from table as t1 inner join
(
select NAME, NUM, max(TIMESTAMP) as TIMESTAMP from table
where BOOL='TRUE'
) as t2
on t1.name=t2.name and t1.num=t2.num and t1.timestamp=t2.timestamp
where t1.BOOL='TRUE'
select t1.*
from TABLE1 as t1
left join
TABLE1 as t2
on t1.name=t2.name and t1.TIMESTAMP>t2.TIMESTAMP
where t1.BOOL='TRUE' and t2.id is null
should do it for you.

Transact SQL - How to perform additional operation on a result set

I have a simple query:
select id, count(*) n
from mytable
group by id
Is it possible to include also the sum(n) in the same query? So the result would look something like this:
id n
---- -----------
1 12
2 1
3 14
4 1
5 2
6 6
Sum=36
You can use a common table expression to do this:
--
; WITH cte as (SELECT id
,count(*) n
FROM mytable
GROUP BY id)
SELECT id, n FROM cte
UNION ALL
SELECT 'Sum', SUM(n) from cte
You can also use ROLLUP: (this may not be exactly correct syntax)
SELECT id
,count(*) n
FROM mytable
GROUP BY id
WITH ROLLUP