Different number of rows for different columns per page - visual-studio

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!

Related

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.

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

Count Length and then Count those records.

I am trying to create a view that displays size (char) of LastName and the total number of records whose last name has that size. So far I have:
SELECT LENGTH(LastName) AS Name_Size
FROM Table
ORDER BY Name_Size;
I need to add something like
COUNT(LENGTH(LastName)) AS Students
This is giving me an error. Do I need to add a GROUP BY command? I need the view:
Name_Size Students
3 11
4 24
5 42
SELECT LENGTH(LastName) as Name_Size, COUNT(*) as Students
FROM Table
GROUP BY Name_Size
ORDER BY Name_Size;
You may have to change the group by and order by to LENGTH(LastName) as not all SQL engines let you reference an alias from the select statement in a clause on that same statement.
HTH,
Eric

How to get records randomly from the oracle database?

I need to select rows randomly from an Oracle DB.
Ex: Assume a table with 100 rows, how I can randomly return 20 of those records from the entire 100 rows.
SELECT *
FROM (
SELECT *
FROM table
ORDER BY DBMS_RANDOM.RANDOM)
WHERE rownum < 21;
SAMPLE() is not guaranteed to give you exactly 20 rows, but might be suitable (and may perform significantly better than a full query + sort-by-random for large tables):
SELECT *
FROM table SAMPLE(20);
Note: the 20 here is an approximate percentage, not the number of rows desired. In this case, since you have 100 rows, to get approximately 20 rows you ask for a 20% sample.
SELECT * FROM table SAMPLE(10) WHERE ROWNUM <= 20;
This is more efficient as it doesn't need to sort the Table.
SELECT column FROM
( SELECT column, dbms_random.value FROM table ORDER BY 2 )
where rownum <= 20;
In summary, two ways were introduced
1) using order by DBMS_RANDOM.VALUE clause
2) using sample([%]) function
The first way has advantage in 'CORRECTNESS' which means you will never fail get result if it actually exists, while in the second way you may get no result even though it has cases satisfying the query condition since information is reduced during sampling.
The second way has advantage in 'EFFICIENT' which mean you will get result faster and give light load to your database.
I was given an warning from DBA that my query using the first way gives loads to the database
You can choose one of two ways according to your interest!
In case of huge tables standard way with sorting by dbms_random.value is not effective because you need to scan whole table and dbms_random.value is pretty slow function and requires context switches. For such cases, there are 3 additional methods:
1: Use sample clause:
https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6
https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6
for example:
select *
from s1 sample block(1)
order by dbms_random.value
fetch first 1 rows only
ie get 1% of all blocks, then sort them randomly and return just 1 row.
2: if you have an index/primary key on the column with normal distribution, you can get min and max values, get random value in this range and get first row with a value greater or equal than that randomly generated value.
Example:
--big table with 1 mln rows with primary key on ID with normal distribution:
Create table s1(id primary key,padding) as
select level, rpad('x',100,'x')
from dual
connect by level<=1e6;
select *
from s1
where id>=(select
dbms_random.value(
(select min(id) from s1),
(select max(id) from s1)
)
from dual)
order by id
fetch first 1 rows only;
3: get random table block, generate rowid and get row from the table by this rowid:
select *
from s1
where rowid = (
select
DBMS_ROWID.ROWID_CREATE (
1,
objd,
file#,
block#,
1)
from
(
select/*+ rule */ file#,block#,objd
from v$bh b
where b.objd in (select o.data_object_id from user_objects o where object_name='S1' /* table_name */)
order by dbms_random.value
fetch first 1 rows only
)
);
To randomly select 20 rows I think you'd be better off selecting the lot of them randomly ordered and selecting the first 20 of that set.
Something like:
Select *
from (select *
from table
order by dbms_random.value) -- you can also use DBMS_RANDOM.RANDOM
where rownum < 21;
Best used for small tables to avoid selecting large chunks of data only to discard most of it.
Here's how to pick a random sample out of each group:
SELECT GROUPING_COLUMN,
MIN (COLUMN_NAME) KEEP (DENSE_RANK FIRST ORDER BY DBMS_RANDOM.VALUE)
AS RANDOM_SAMPLE
FROM TABLE_NAME
GROUP BY GROUPING_COLUMN
ORDER BY GROUPING_COLUMN;
I'm not sure how efficient it is, but if you have a lot of categories and sub-categories, this seems to do the job nicely.
-- Q. How to find Random 50% records from table ?
when we want percent wise randomly data
SELECT *
FROM (
SELECT *
FROM table_name
ORDER BY DBMS_RANDOM.RANDOM)
WHERE rownum <= (select count(*) from table_name) * 50/100;

Oracle aggregate function to return a random value for a group?

The standard SQL aggregate function max() will return the highest value in a group; min() will return the lowest.
Is there an aggregate function in Oracle to return a random value from a group? Or some technique to achieve this?
E.g., given the table foo:
group_id value
1 1
1 5
1 9
2 2
2 4
2 8
The SQL query
select group_id, max(value), min(value), some_aggregate_random_func(value)
from foo
group by group_id;
might produce:
group_id max(value), min(value), some_aggregate_random_func(value)
1 9 1 1
2 8 2 4
with, obviously, the last column being any random value in that group.
You can try something like the following
select deptno,max(sal),min(sal),max(rand_sal)
from(
select deptno,sal,first_value(sal)
over(partition by deptno order by dbms_random.value) rand_sal
from emp)
group by deptno
/
The idea is to sort the values within group in random order and pick the first.I can think of other ways but none so efficient.
You might prepend a random string to the column you want to extract the random element from, and then select the min() element of the column and take out the prepended string.
select group_id, max(value), min(value), substr(min(random_value),11)
from (select dbms_random.string('A', 10)||value random_value,foo.* from foo)
In this way you cand avoid using the aggregate function and specifying twice the group by, which might be useful in a scenario where your query is very complicated / or you are just exploring the data and are entering manually queries with a lengthy and changing list of group by columns.

Resources