start wih connect by in netezza - sql

Imagine the following table
DEPARTURE_ID ARRIVE_ID ORDER
------------- --------- -----
1 3 1
2 3 2
3 (null) 3
10 12 1
11 13 2
12 15 3
13 15 4
14 15 5
15 (null) 6
25 27 1
26 27 2
27 (null) 3
I want to keep the departure_id(s) connected by the prior arrive_id(s)
In oracle11g, I do this
Sample Table
create table dep_arrives ( departureid, arrriveid, ord) as
select '1', '3', 1 from dual union all
select '2', '3', 2 from dual union all
select '3', null, 3 from dual union all
select '10', '12', 1 from dual union all
select '11', '13', 2 from dual union all
select '12', '15', 3 from dual union all
select '13', '15', 4 from dual union all
select '14', '15', 5 from dual union all
select '15', null, 6 from dual union all
select '25', '27', 1 from dual union all
select '26', '27', 2 from dual union all
select '27', null, 3 from dual
;
Select statement
select departureid
from dep_arrives
start with ord = 1
connect by departureid = prior arrriveid
Result
DEPARTURE_ID
1
3
10
12
15
25
27
I know there is no start with connect by in netezza so I'm looking for a workaround with netezza sql.
Thanks in advance.

Related

sql function to create sequential for repeated item- [duplicate]

This question already has an answer here:
Add a sequence column in a query
(1 answer)
Closed 7 days ago.
I would like to know if there is an easy sql function to do a sequential classification for each duplicate record as shown in the image:
enter image description here
Looks like one of analytic functions, such as row_number (or perhaps rank).
Sample data:
SQL> with test (product, value) as
2 (select 'A', 100 from dual union all
3 select 'B', 100 from dual union all
4 select 'C', 100 from dual union all
5 select 'A', 100 from dual union all
6 select 'B', 100 from dual union all
7 select 'A', 100 from dual union all
8 select 'D', 100 from dual union all
9 select 'D', 100 from dual union all
10 select 'F', 100 from dual union all
11 select 'F', 100 from dual union all
12 select 'F', 100 from dual
13 )
Query:
14 select product, value,
15 row_number() over (partition by product order by null) classification
16 from test
17 order by product;
PRODUCT VALUE CLASSIFICATION
---------- ---------- --------------
A 100 1
A 100 2
A 100 3
B 100 1
B 100 2
C 100 1
D 100 1
D 100 2
F 100 1
F 100 2
F 100 3
11 rows selected.
SQL>

Oracle SQL Grouping In Ranges

I am looking for ideas on how to group numbers into low and high ranges in Oracle SQL. I looking to to avoid cursors...any ideas welcome
Example input
ID
LOW
HIGH
A
0
2
A
2
3
A
3
5
A
9
11
A
11
13
A
13
15
B
0
1
B
1
4
B
7
9
B
11
12
B
12
17
B
17
18
Which would result in the following grouping into ranges
ID
LOW
HIGH
A
0
5
A
9
15
B
0
4
B
7
9
B
11
18
This is a Gaps & Islands problem. You can use the traditional solution.
For example:
select max(id) as id, min(low) as low, max(high) as high
from (
select x.*, sum(i) over(order by id, low) as g
from (
select t.*,
case when low = lag(high) over(partition by id order by low)
and id = lag(id) over(partition by id order by low)
then 0 else 1 end as i
from t
) x
) y
group by g
Result:
ID LOW HIGH
--- ---- ----
A 0 5
A 9 15
B 0 4
B 7 9
B 11 18
See running example at db<>fiddle.
From Oracle 12, you should use MATCH_RECOGNIZE for row-by-row pattern matching:
SELECT *
FROM table_name
MATCH_RECOGNIZE(
PARTITION BY id
ORDER BY low, high
MEASURES
FIRST(low) AS low,
MAX(high) AS high
PATTERN (overlapping* last_row)
DEFINE
overlapping AS NEXT(low) <= MAX(high)
)
Which, for the sample data:
CREATE TABLE table_name (id, low, high) AS
SELECT 'A', 0, 2 FROM DUAL UNION ALL
SELECT 'A', 2, 3 FROM DUAL UNION ALL
SELECT 'A', 3, 5 FROM DUAL UNION ALL
SELECT 'A', 9, 11 FROM DUAL UNION ALL
SELECT 'A', 11, 13 FROM DUAL UNION ALL
SELECT 'A', 13, 15 FROM DUAL UNION ALL
SELECT 'B', 0, 1 FROM DUAL UNION ALL
SELECT 'B', 1, 4 FROM DUAL UNION ALL
SELECT 'B', 7, 9 FROM DUAL UNION ALL
SELECT 'B', 11, 12 FROM DUAL UNION ALL
SELECT 'B', 12, 17 FROM DUAL UNION ALL
SELECT 'B', 17, 18 FROM DUAL UNION ALL
SELECT 'C', 0, 10 FROM DUAL UNION ALL
SELECT 'C', 1, 3 FROM DUAL UNION ALL
SELECT 'C', 5, 8 FROM DUAL UNION ALL
SELECT 'C', 9, 15 FROM DUAL UNION ALL
SELECT 'C', 10, 14 FROM DUAL UNION ALL
SELECT 'C', 11, 13 FROM DUAL;
Outputs:
ID
LOW
HIGH
A
0
5
A
9
15
B
0
4
B
7
9
B
11
18
C
0
15
fiddle

Compute "Amount" using values from tables

I have the following tables already in my DB
EMP
E_N E_NAM E_RATE E_DEP
--- ----- ---------- -----
1 A 400
2 B 200 1
3 C 150 2
4 D 150 3
5 E 120 1
6 F 100 1
7 G 100 2
8 H 50 2
9 I 50 3
10 J 50 3
11 K 150 3
WORKS
E_NO PR_NO HRS
--- --- ----------
2 1 10
3 2 20
5 1 20
5 2 20
5 3 20
6 1 10
6 2 10
I have to compute the amount billed to each project as AMOUNT, and that is the sum of the amount billed to the project by all employees who work on said project. The amount billed being E_RATE*HRS (product of HRS and E_RATE).
There are only 3 PR_NO: 1, 2 and 3.
I've tried this multiple times with no avail, I know that it has to be a nested query and the calculation to be shown AS AMOUNT, but no clue on how exactly to only display the 3 projects with the calculation already made.
Sounds like simple join and aggregation:
select w.pr_no,
sum(w.hrs * e.e_rate) as amount
from works w
join emp e on w.e_no = e.e_n
group by w.pr_no;
simple aggregate SUM() function after joining the tables
--test data
with EMP(e_no, e_name, e_rate, e_dep) as
(select 1, 'A', 400, null from dual union all
select 2, 'B', 200, 1 from dual union all
select 3, 'C', 150, 2 from dual union all
select 4, 'D', 150, 3 from dual union all
select 5, 'E', 120, 1 from dual union all
select 6, 'F', 100, 1 from dual union all
select 7, 'G', 100, 2 from dual union all
select 8, 'H', 50, 2 from dual union all
select 9, 'I', 50, 3 from dual union all
select 10, 'J', 50, 3 from dual union all
select 11, 'K', 150, 3 from dual),
WORKS(e_no, pr_no, hrs) as
(select 2, 1, 10 from dual union all
select 3, 2, 20 from dual union all
select 5, 1, 20 from dual union all
select 5, 2, 20 from dual union all
select 5, 3, 20 from dual union all
select 6, 1, 10 from dual union all
select 6, 2, 10 from dual)
-- actual query starts here
select w.pr_no, sum(w.hrs*e.e_rate) as amount
from works w
inner join emp e on (w.e_no = e.e_no)
group by w.pr_no;
"PR_NO"|"AMOUNT"
1|5400
2|6400
3|2400

How to get the max count of coherently cells?

I have following data in my table:
ID - Data
1 - 0
2 - 10
3 - 100
4 - 60
5 - 0
6 - 0
7 - 15
8 - 100
9 - 100
10 - 70
11 - 10
12 - 0
13 - 0
What I want is the max count of rows > 0.
This data shows the energy using of a device in percent of a given total.
What I basicly want to know is: how long is the device "on" the longest timeperiod?
I guess you are expecting result 5 (longest sequence of non-zero numbers) for your example data. You can do that with recursive CTE in Oracle:
with testData as (
select '1' id, '0' val from dual
union all
select '2', '10' from dual
union all
select '3', '100' from dual
union all
select '4', '60' from dual
union all
select '5', '0' from dual
union all
select '6', '0' from dual
union all
select '7', '15' from dual
union all
select '8', '100' from dual
union all
select '9', '100' from dual
union all
select '10', '70' from dual
union all
select '11', '10' from dual
union all
select '12', '0' from dual
union all
select '13', '0' from dual
) ,
cte (id, val, sumX) as (
select t.id, val, case when val !=0 then 1 else 0 end from testData t where id = 1
union all
select t.id, t.val, case when t.val !=0 then sumX+1 else 0 end
from testData t
inner join cte
on cte.id = t.id-1
)
select max(sumx) from cte

Oracle SQL dynamically select column name

A user gave me a table that looks like the following.
Name HH08 HH09 HH10 HH11 HH12 HH13
Bob 2 3 4 2 7 1
Steve 2 9 3 2 2 5
Mike 2 2 2 2 3 2
Pat 1 0 2 0 0 0
I need some sql that will select the row based on the name, and the column based on the current hour of sysdate when the query is run.
If it is 9:27 am and the user is Steve, the sql needs to select the 9 value.
Is there any simple sql that will do this, or do I need to restructure the table the user gives me, which will be occassionally.
Thanks in advance.
Try:
select case to_char(sysdate,'hh24')
when '08' then hh08
when '09' then hh09
when '10' then hh10
when '11' then hh11
when '12' then hh12
when '13' then hh13
end OutputValue
from TableName
WHERE Name = 'Steve'
SELECT 'HH'+convert(char(2),DATEPART(hour,getdate()))
FROM TableName
WHERE Name = 'Steve'
try this out
with t as (
select 'Bob' name, 2 hh08, 3 hh09, 4 hh10, 2 hh11, 7 hh12, 1 hh13 from dual union all
select 'Steve', 2, 9, 3, 2, 2, 5 from dual union all
select 'Mike', 2, 2, 2, 2, 3, 2 from dual union all
select 'Pat', 1, 0, 2, 0, 0, 0 from dual
)
--/\-- Data sample --/\--
select value from t
unpivot(value for hr in (hh08 as '08', hh09 as '09', hh10 as '10', hh11 as '11', hh12 as '12', hh13 as '13') )
where hr = to_char(sysdate, 'HH24')
and name = 'Pat';