selecting first result from output of a subquery - sql

i want to select first and last outcome from a subquery in oracle.
i cant use "rownum" since i am using "order by" which completely changes the sequence of "rownum".
pls suggest some solutions.
thanx fr help.

Use keep if you have an aggregation query. That is what it is designed for. It looks something like this:
select x,
max(outcome) keep (dense_rank first order by datetime asc) as first_outcome,
max(outcome) keep (dense_rank first order by datetime desc) as last_outcome,
from t
group by x;
Use first_value() and last_value() if there is no aggregation:
select t.*,
first_value(outcome) over (partition by x order by datetime) as first_outcome,
last_value(outcome) over (partition by x order by datetime) as last_outcome
from t;

You can't use "rownum" because you want both the first and the last values - otherwise you could use rownum by putting your code in a subquery and selecting from it and filtering by rownum in the outer query. As it is, you need to use ROW_NUMBER() analytic function and such (both with order by ... and with order by ... desc, so you can get both the first and the last outcome in one single outer query.
If ties are possible you may prefer DENSE_RANK to get all rows tied for first (or for last); instead, ROW_NUMBER() will return "one of" the rows tied for first (or for last); which one, specifically, is random.
If you want to see an example, provide sample data for your problem.

I solved this by using ROW_NUMBER() function with OVER(order by..).

Related

Why is order by required inside OVER when using LEAD in SQL?

SELECT seller_name, sale_value,
LEAD(sale_value) OVER(ORDER BY sale_value) as next_sale_value
FROM sale
ORDER BY sale_value
Am I right to understand that lead must compulsorily have over(order by..) because the SELECT is executed before the final ORDER BY statement?
The ORDER BY is required in the OVER clause, not in the outer query. So this is fine:
SELECT seller_name, sale_value,
LEAD(sale_value) OVER (ORDER BY sale_value) as next_sale_value
FROM sale;
However, the results may be in any arbitrary order.
Why does LEAD() require the ORDER BY? Well the definition of LEAD() is to pull the value from the "next" row. However, SQL tables represent unordered (multi)sets. There is no next row unless a column or expression defines it -- and that is what the OVER ( . . . ORDER BY) defines.

How can we implement First() function used in Informatica in SQL?

I have an aggregate transformation in Informatica where Description1 column=First(Description).
I want to implement the same in SQL query.Can anyone suggest how to do this?
Sample Dataset
Table name-ABC
Name Expression
ID ID
DESCRIPTION
DESCRIPTION1 FIRST(DESCRIPTION1)
INSERT_DATE
INSERT_DATE1 FIRST(INSERT_DATE)
RANK
RANK1 FIRST(RANK)
Please use below query,
select max(Description1) from Router_Transform;
If you are using sorter transformation in your Mapping, please use order by clause,
select max(Description1) from Router_Transform order by column_name;
If you want the row with the smallest id, then you can sort the resultset and retain just one row. In standard SQL, you would typically use a row-limiting clause for this:
select t.*
from mytable
order by id
fetch first row only
Note that all databases support this syntax (but almost all have alternatives for that).
On the other hand, if you want to add more columns to each row that display the "first" value for each column, then you would use window function first_value():
select
t.*,
first_value(description) over(order by id) description1,
first_value(insert_date) over(order by id) insert_date1,
first_value(rank) over(order by id) rank1
from mytable

How to add a row number within a group in my query

I've tried this query:
SELECT X,Y,Z,COUNT(*)
FROM TABLE1
GROUP BY X,Y,Z
and my result is:
but I need the following result:
This should do the trick:
SELECT X,Y,Z,ROW_NUMBER() OVER (PARTITION BY X,Y,Z ORDER BY X,Y,Z)
FROM TABLE1
The ROW_NUMBER() will tick up for every value in the group X,Y,Z, and reset at a next group. The ORDER BY clause is used to define in what order it should tick up, and can be changed to however you wish. This is one of the analytical functions Oracle provides, and can be very useful.

SQL random aggregate

Say I have a simple table with 3 fields: 'place', 'user' and 'bytes'. Let's say, that under some filter, I want to group by 'place', and for each 'place', to sum all the bytes for that place, and randomly select a user for that place (uniformly from all the users that fit the 'where' filter and the relevant 'place'). If there was a "select randomly from" aggregate function, I would do:
SELECT place, SUM(bytes), SELECT_AT_RANDOM(user) WHERE .... GROUP BY place;
...but I couldn't find such an aggregate function. Am I missing something? What could be a good way to achieve this?
If your RDBMS supports analytical functions.
WITH T
AS (SELECT place,
Sum(bytes) OVER (PARTITION BY place) AS Sum_bytes,
user,
Row_number() OVER (PARTITION BY place ORDER BY random_function()) AS RN
FROM YourTable
WHERE .... )
SELECT place,
Sum_bytes,
user
FROM T
WHERE RN = 1;
For SQL Server Crypt_gen_random(4) or NEWID() would be examples of something that could be substituted in for random_function()
I think your question is DBMS specific. If your DBMS is MySql, you can use a solution like this:
SELECT place_rand.place, SUM(place_rand.bytes), place_rand.user as random_user
FROM
(SELECT place, bytes, user
FROM place
WHERE ...
ORDER BY rand()) place_rand
GROUP BY
place_rand.place;
The subquery orders records in random order. The outer query groups by place, sums bytes, and returns first random user, since user is not in an aggregate function and neither in the group by clause.
With a custom aggregate function, you could write expressions as simple as:
SELECT place, SUM(bytes), SELECT_AT_RANDOM(user) WHERE .... GROUP BY place;
SELECT_AT_RAMDOM would be the custom aggregate function.
Here is precisely an implementation in PostgreSQL.
I would do a bit of a variation on Martin's solution:
select place, sum(bytes), max(case when seqnum = 1 then user end) as random_user
from (select place, bytes,
row_number() over (partition by place order by newid()) as sequm
from t
) t
group by place
(Where newid() is just one way to get a random number, depending on the database.)
For some reason, I prefer this approach, because it still has the aggregation function in the outer query. If you are summarizing a bunch of fields, then this seems cleaner to me.

Oracle: Display row number with 'order by' clause

I wonder how could i print a row number for sql statement where is using order.
Currently i tried ROWNUM but as i understand it works only for unsorted result set.
SELECT rownum, a.lg_id, a.full_name, a.sort_order
FROM activity_type_lang a
where a.lg_id = 'en'
order by a.full_name;
TIA
In addition to nesting the query, you can use an analytic function
SELECT row_number() OVER (ORDER BY a.full_name),
lg_id,
full_name,
sort_order
FROM activity_type_lang a
WHERE a.lg_id = 'en'
ORDER BY a.full_name
Using analytic functions also makes it easier if you want to change how ties are handled. You can replace ROW_NUMBER with RANK or DENSE_RANK.
Oh. Seems i've found already a solution.
Select rownum, lg_id, full_name, sort_order from
(SELECT a.lg_id, a.full_name, a.sort_order
FROM activity_type_lang a
where a.lg_id = 'en'
order by a.full_name);
rownum is applied before ordering, so you have to rewrite your query like this:
select rownum, xxx.* from (
SELECT a.lg_id, a.full_name, a.sort_order
FROM activity_type_lang a
where a.lg_id = 'en'
order by a.full_name
) xxx;
Hello. I wonder how could i print a
row number for sql statement where is
using order. Currently i tried ROWNUM
but as i understand it works only for
unsorted result set.
To be clear (somebody might get it wrong). It does work (but not in the way you expect). The problem with it is that it "attaches" the ROWNUM before the sort and you get your records but not in consecutive ROWNUM records. Why? Because
The first record that meets the where
criteria in a select statement is
given rownum=1
This is really good example how select / order mechanism works.