Adding a resetting counter (reset on a column's value change) to a PLSQL line in a view - oracle

I am using PL SQL developer and Oracle 11g. Here is my issue:
EDIT
It looks like using rank (partition by header number, line number order by date) works.
I would like to create a counter that changes each time a column has a different value than the last. I need to be able to do this in a view (non-modifiable constraint). The goal would be to use this counter to build a new unique key into that view. Thus, I need to reset the 'counter' each time a line number changes in the planning table (see below).
I have 3 tables. Under each table I have put some important columns:
Header
--headerNumber (unique)
Detail
--headerNumber (not unique)
--lineNumber (unique)
Planning lines
--headerNumber (not unique)
--lineNumber (not unique)
--some date
Into the planning lines table, there exist multiple lines, per line number as well. I want to build into a view (this is a constraint, it must be a view) the ability to build a unique number off of the line number from planning.
Here is some example data:
Header (1 row):
Header Number = 1
Detail (2 rows)
Header Number = 1, LineNumber = 1
Header Number = 1, LineNumber = 2
Planning (4 rows)
Header Number = 1, Line number = 1, date = 01/01/14
Header Number = 1, Line number = 1, date = 01/02/14
Header Number = 1, Line Number = 2, date = 01/01/14
Header Number = 1, Line Number = 2, date = 01/03/14
Into the view I want it to look like this:
HeaderNumber | Line Number | 'Counter' (What I am trying to create)
1 | 1 | 1
1 | 1 | 2
1 | 2 | 1
1 | 2 | 2
Here are some final issues I have faced:
It does not appear as if I can use row number -- The view will contain multiple headers, and more importantly, row number seems to be built out of the entire select's contents -- thus I can't trim it. Row number ends up counting 1,2,3,4 (row above).
Does anyone have an idea about how to build this into a select (to put into a view)? I know this can be done by a procedure but I really need a view.
Regards,
Seriously Confused Man

I'm not sure what you have tried exactly when you say "row number" - do you mean ROWNUM or row_number()?
Doesn't this do what you want?
select headernumber, linenumber,
row_number() over (partition by headernumber order by linenumber)
as counter
from ...;

Related

Fetch substring from right side

I am using oracle. i have a column "ITEM_FINAL" consisting of a string which is a combination of 2 records.
ITEM_FINAL = ITEM_ID + ITEM
I need to segregate ITEM_FINAL and put them into 2 different columns ITEM_ID and ITEM.
However the length of the ITEM_ID is not constant, it can be 1 or 10 or 999 (till 3 digits).
ITEM is constant and it will be 5 digits always.
Eg. ITEM_FINAL = 1256789 (combination of 12 + 56789) or 256789 (combination of 2 + 56789)
I can fetch ITEM details with help of substr
select substr(ITEM_FINAL,-5) from dual;
It will give the last 5 digits (56789) which is constant. How can i fetch the remaining string from 6th position till the start irrespective of length from right hand side for ITEM_ID column
select substr(ITEM_FINAL, 1, length(ITEM_FINAL)-5) ITEM_ID,
substr(ITEM_FINAL,-5) ITEM
from dual;

Complex count row etl requirement

I have a requirement related as below
1-If there is employee record then count the number of rows
a-if there are four rows then follow the layout 1,
and populate the column1 and column 2 with values in report and ltrimrtrim
b- if there are three rows, then follow the layout 2,
and hardcode the column 1 and column 2 with NULL
Otherwise, look for the employee record.
Couldn't get the logic, I used the router with as if column 1 and two null the send to layout two else 1. But the requirement is different.
router transformation, if null, layout one else 2
Step 1 - Use SRT>AGG>JNR to calculate count. create new column as count_all and set to COUNT(*). Please group by proper key columns.
Step 2 - Use RTR next to split data based on your condition.
group 1- count_all =4 then follow the layout 1 and...
group 2- count_all =3 then follow the layout 2 and...
group 3 - if count <3 then do employee record.

Different number of rows for different columns per page

I have a SSRS report in which there are 3 columns each contain 3 different subreports in a table. Requirement is 1st subreport column should return 27 rows, 2nd : 25 rows and 3rd:26 rows. Is it possible in SSRS ? If yes How ?
You can do this.. using row_number and Mod.
I'm simply generating a list of numbers from 1 - 100 below.. lets assume that this is your dataset. Create a new column using row_number and partition it by mod 25 (27 or 26 as you require) against this dataset. Now you have a unique value every X number of rows..
declare #start int = 1
declare #end int = 100
;with mycte as (
select distinct n = number
from master..[spt_values]
where number between #start and #end
)
Select
*
,ROW_NUMBER() OVER (PARTITION BY (mycte.n % 25) ORDER BY (n) )rn
from mycte
order by 1,2
Now in SSRS, against each subreport add this column, add a parent group, grouping by this newly generated row number (RN in this case). Remove any columns that SSRS adds after grouping, but keep the grouping..
Set the group property to pagebreak in between each instance of the groups.. Done!

Add blank rows between a group of mutliple rows - Oracle

Is there a possibility to add blank rows in a group of data rows dynamically ? I have the below query which fetches data in multiple rows. I want to separate, say add blank row after each 5 rows.
The query :
select php.ref_dcp_key, sum(php.group_booking), count(php.group_booking), 0
from gx_pnr_history ph, gx_pnr_his_prof php
where ph.gmpnr_loc_key = php.gmpnr_loc_key
group by php.ref_dcp_key order by php.ref_dcp_key;
#SandeepGowada, you'd have to create an outer structure for the rows and put in the 6th padding row after every 5 data rows.
I second the view of #juergend that this should really be done in the presentation layer (although often it probably requires no less code overall to do it there than in SQL - but it does frustrate the workings of anything other than a static report, like datagrids that allow re-sorting or filtering)
I've knocked together some untested code (using Oracle syntax) which shows an example of how it's done - how we prepare the base data, then build a table of placeholders for all necessary rows, then join the base data onto the placeholders in the appropriate places. I've made some of the calculations a bit more elaborate to show where the number 5 constant is being used.
Also, I haven't included any code to knock off any surplus padding rows in the final group (i.e. as it stands the number of rows returned will always be a multiple of 6, regardless of the underlying data).
Nor have I included any code regarding the required numbers_table or sequence generator.
WITH base_data AS
(
SELECT
php.ref_dcp_key
,sum(php.group_booking) AS group_booking_sum
,count(php.group_booking) AS group_booking_count
,0 AS zero_value_column
,MOD(ROW_NUMBER() OVER (ORDER BY php.ref_dcp_key) - 1, 5) AS group_line_num
,( (ROW_NUMBER() OVER (ORDER BY php.ref_dcp_key) + (5 - 1)) / 5 ) AS row_group_num
--all appearances of the number 5 constants determine the number of lines per group
FROM
gx_pnr_history /*AS*/ ph
INNER JOIN
gx_pnr_his_prof /*AS*/ php
ON (ph.gmpnr_loc_key = php.gmpnr_loc_key)
GROUP BY
php.ref_dcp_key
)
,row_structure AS
(
SELECT
MOD(number - 1, (5 + 1)) AS group_line_num
,number + ((5 + 1) - 1) / (5 + 1) AS row_group_num
FROM
number_table /*this needs to be a reference either to a numbers table, or a number sequence generator*/
WHERE
number BETWEEN 1 AND ((SELECT MAX(row_group_num) * (5 + 1) FROM base_data))
)
SELECT
ref_dcp_key
,group_booking_sum
,group_booking_count
,zero_value_column
,ROW_NUMBER() OVER (ORDER BY row_structure.row_group_num ASC, row_structure.group_line_num ASC) AS final_order
FROM
row_structure
LEFT JOIN
base_data
ON (base_data.row_group_nun = row_structure.row_group_num)
AND (base_data.group_line_num = row_structure.group_line_num)
ORDER BY
final_order

Stacked column Flash chart counting all values

I am building stacked column flash chart on my query. I would like to split values in column for different locations. For argument sake I have 5 ids in location 41, 3 ids in location 21, 8 ids in location 1
select
'' link,
To_Char(ENQUIRED_DATE,'MON-YY') label,
count(decode(location_id,41,id,0)) "location1",
count(decode(location_id,21,id,0)) "location2",
count(decode(location_id,1,id,0)) "location3"
from "my_table"
where
some_conditions = 'Y';
as a result of this query Apex is creating stacked column with three separate parts( hurray!), however it instead of having values 5,3 and 8, it returns three regions 16,16,16. ( 16 = 5 +3+8).
So obviously Apex is going through all decode conditions and adding all values.
I am trying to achieve something described in this
article
Apex doesn't appear to be doing anything funky, you'd get the same result running that query through SQL*Plus. When you do:
count(decode(location_id,41,id,0)) "location1",
.. then the count gets incremented for every row - it doesn't matter which column you include, and the zero is just treated as any fixed value. I think you meant to use sum:
sum(decode(location_id,41,1,0)) "location1",
Here each row is assigned either zero or one, and summing those gives you the number that got one, which is the number that had the specified id value.
Personally I'd generally use caseover decode, but the result is the same:
sum(case when location_id = 41 then 1 else 0 end) "location1",

Resources