Ranking in SSRS 2008 - ranking

I have a report in SSRS grouped by Property Name and I would like to rank the bookings and revenue columns across all the Properties. If anyone could give some advice on how to do this, it would be much appreciated.

You could add two attributes to the SELECT clause in your dataset
SELECT ...
, RANK() OVER (PARTITION BY PropertyName ORDER BY SUM(Bookings) DESC) AS BookingRank
, RANK() OVER (PARTITION BY PropertyName ORDER BY SUM(Revenue) DESC) AS RevenueRank
...
RANK omits a number in case of ties, e.g. 1,2,2,4,5
DENSE_RANK would instead give you 1,2,2,3,4 instead for ties on row 2 and 3..

Related

In case second highest value is missing then use the highest value of salary from employee table

I have an employee table as below. As you can see that second highest salary is 200
Incase the second highest salary is missing then there will be only one row as shown at last . In this case the query should fetch only 100
I have written query as but it is not working. Please help! Thanks
select salary "SecondHighestSalary" from(
(select id,salary,rank() over(order by salary desc) rnk
from employee2)
)a
where (rnk) in coalesce(2,1)
I have also tried the following but it is fetching 2 rows but i need only 1
It sounds like you'd want something like
with ranked_emp as (
select e.*,
rank() over (order by e.sal desc) rnk,
count(*) over () cnt
from employee2 e
)
select salary "SecondHighestSalary"
from ranked_emp
where (rnk = 2 and cnt > 1)
or (rnk = 1 and cnt = 1)
Note that I'm still using rank since you're using that in your approach and you don't specify how you want to handle ties. If there are two employees with the same top salary, rank will assign both a rnk of 1 and no employee would have a rnk of 2 so the query wouldn't return any data. dense_rank would ensure that there was at least one employee with a rnk of 2 if there were employees with at least 2 different salaries. If there are two employees with the same top salary, row_number would arbitrarily assign one the rnk of 2. The query I posted isn't trying to handle those duplicate situations because you haven't outlined exactly how you'd want it to behave in each instance.
If you are in Oracle 12.2 or higher, you can try:
select distinct id,
nvl
(
nth_value(salary, 2) from first
over(partition by id
order by salary desc
range between unbounded preceding and unbounded
following),
salary
) second_max_salary
from employee2

how to use rownumber over partition in ODI MAPPING

My requirement is to get the recent record grouped by columns c1,c2.I have 50 columns in my source, using query i can apply rownumber() over partition by c1,c2 order by record_time desc, and pick the record where rownumber=1. In short, my oracle query would be:
select c1,c2,....,c50
from (select c1,c2,....,c50,
row_number() over (partition by c1,c2 order by record_time desc ) rn
from table)
where rn = 1;
How can I achieve this using ODI mapping? Please suggest.
Thanks
You have not mentioned the version of ODI you are using, assuming you are using ODI 11g. You can create a yellow interface and create a column for rownum with expression as below
row_number() over (partition by c1,c2 order by record_time desc)
Now use this yellow interface as source in your interface and apply filter on rownum column as below
rownum = 1
While using this you will have to make sure your KM is not adding group by function, else it'll end up in error.

use RANK or DENSE_RANK along with aggregate function

I have a table with the following data:
SCORE ROW_ID NAME
0.4 1011 ABC
0.95 1011 DEF
0.4 501 GHI
0.95 501 XYZ
At any point of time, i only need single row of data with maximum score, if there has more than 1 records, take the one with minimum row_id.
Is it possible to achieve by using RANK or DENSE_RANK function? How about partition by?
MAX(score) keep(dense_rank first order by row_id)
You are looking for max score, one row, so use row_number():
select score, row_id, name
from (select t.*, row_number() over (order by score desc, row_id) rn from t)
where rn = 1
demo
You can use rank and dense_rank in your example, but they can return more than one row, for instance when you add row (0.95, 501, 'PQR') to your data.
keep dense_rank is typically used when searched value is other than search criteria, for instance if we look for salary of employee who works the longest:
max(salary) keep (dense_rank first order by sysdate - hiredate desc)
max in this case means that if there are two or more employees who works longest, but exactly the same number of days than we take highest salary.
max(salary)
keep (dense_rank first order by sysdate - hiredate desc)
over (partition by deptno)
This is the same as above, but salary of longest working employees is shown for each department separately. You can even use empty over() to show salary of longest working employee in separate column except other data like name, salary, hire_date.
You dont need to use dense_rank. This would help
SELECT * FROM (
SELECT
SCORE,
ROW_ID
NAME
FROM T
ORDER BY SCORE DESC, ROW_ID DESC
)
WHERE ROWNUM = 1;

how to display identical values in a single column using EXCEL or ORACLE

Hello I need a formula in column ā€˜Cā€™ which calculates/adds the amount of B Column based on the column A ID. If there are several amounts in same ID it should add the total amount and would show the result in column ā€˜Cā€™ as a single row.
the output can be obtained from Oracle SQL query or an Excel formula.your help would be appreciated.
You can get the same output from Oracle itself, using analytical functions like below.
SUM() OVER(PARTITION BY ... ) -> This actually do the cumulative sum
WITH MYTABLE(ID,AMT) AS
(SELECT '2UF2', '500' FROM DUAL
UNION ALL
SELECT '2TC6', '300' FROM DUAL
UNION ALL
SELECT '2TC6', '200' FROM DUAL
UNION ALL
SELECT '2TC6', '800' FROM DUAL
)
SELECT ID,
AMT,
CASE ROW_NUMBER() OVER(PARTITION BY ID ORDER BY NULL)
WHEN 1
THEN SUM(AMT) OVER(PARTITION BY ID ORDER BY NULL)
END AS FORMULA
FROM MYTABLE
ORDER BY ID, FORMULA NULLS LAST;
SQL Fiddle Demo
You can use rollup in oracle
Select id,amt,sum (amt) nullFrom table nullGroup by rollup (id,amt)
For more details see below link
https://oracle-base.com/articles/misc/rollup-cube-grouping-functions-and-grouping-sets
In SQL you need an aggregation function, in this case sum, and a group by clause. The generic query should look like the following:
Select sum(b) from table group by a
I hope this helps.

Joining the top result in Oracle

I'm using this query:
SELECT *
FROM HISTORY
LEFT JOIN CUSTOMER ON CUSTOMER.CUST_NUMBER = HISTORY.CUST_NUMBER
LEFT JOIN (
Select LOAN_DATE, CUST_NUMBER, ACCOUNT_NUMBER, STOCK_NUMBER, LOC_SALE
From LOAN
WHERE ACCOUNT_NUMBER != 'DD'
ORDER BY LOAN_DATE DESC
) LOAN ON LOAN.CUST_NUMBER = HISTORY.CUST_NUMBER
order by DATE desc
But I want only the top result from the loan table to be joined (Most recent by Loan_date). For some reason, it's getting three records (one for each loan on the customer I'm looking at). I'm sure I'm missing something simple?
If you're after joining the latest loan row per cust_number, then this ought to do the trick:
select *
from history
left join customer on customer.cust_number = history.cust_number
left join (select loan_date,
cust_number,
account_number,
stock_number,
loc_sale
from (select loan_date,
cust_number,
account_number,
stock_number,
loc_sale,
row_number() over (partition by cust_number
order by loan_date desc) rn
from loan
where account_number != 'DD')
where rn = 1) loan on loan.cust_number = history.cust_number
order by date desc;
If there are two rows with the same loan_date per cust_number and you want to retrieve both, then change the row_number() analytic function for rank().
If you only want to retreive one row, then you'd have to make sure you add additional columns into the order by, to make sure that the tied rows always display in the same order, otherwise you could find that sometimes you get different rows returned on subsequent runs of the query.

Resources