How to get a value from previous result row of a SELECT statement
If we have a table called cardevent and has rows [ID(int) , Value(Money) ] and we have some rows in it, for example
ID --Value
1------70
1------90
2------100
2------150
2------300
3------150
3------200
3-----250
3-----280
so on...
How to make one Query that get each row ID,Value and the previous Row Value in which data appear as follow
ID --- Value ---Prev_Value
1 ----- 70 ---------- 0
1 ----- 90 ---------- 70
2 ----- 100 -------- 90
2 ------150 -------- 100
2 ------300 -------- 150
3 ----- 150 -------- 300
3 ----- 200 -------- 150
3 ---- 250 -------- 200
3 ---- 280 -------- 250
so on.
So can anyone help me to get the best solution for such a problem ?
Need Query Help
SELECT t.*,
LAG(t.Value) OVER (ORDER BY t.ID)
FROM table AS t
This should work.
The Lag function gets the previous row value for a specific column. I think this is what you want here.
You can use LAG() and LEAD() Function to get previous and Next values.
SELECT
LAG(t.Value) OVER (ORDER BY t.ID) PreviousValue,
t.value Value,
LEAD(t.value) OVER (ORDER BY t.ID) NextValue
FROM table t
GO
You would have to join the table with itself, I'm not sure if this is 100% legitimate SQL, but I have no SQL-Server to try this at the moment, but try this:
SELECT (ID, Value) from table as table1
inner join table as table2
on table1.ID = (table2.ID -1)
select t1.value - t2.value from table t1, table t2
where t1.primaryKey = t2.primaryKey - 1
Try this.
Related
this is my table:
ID/Number/Date
1/111/2021-01-01
2/111/2021-01-02
6/333/2921-01-01
I need a table which count the rows based on Number order by Date asc.
This should be my final table:
ID/Number/Date/Row_No_Count
1/111/2021-01-01/1
2/111/2021-01-02/2
6/333/2921-01-01/1
How to achieve this with hive? Is their any function?
Row Number is a Function IN SQL Server for this type of Work.
You can solve Your Problem on based on below Query .
Query : Select *,row_number () Over (partition by Number order by Number) 'Row_Number_Count' From t ;
Output :
id Number Date Row_Number_Count
----------- ----------- ---------- --------------------
1 111 2021-01-01 1
2 111 2021-01-02 2
6 333 2921-01-01 1
(3 rows affected)
try row_number() window function like below.
select t.*,
row_number() over(partition by Number order by Number,Date asc ) as Row_No_Count
from table t
Can I use LISTAGG or a similar analytical function in Oracle SQL to display all values in group up to current record?
This is my table:
id group_id value
-- -------- -----
1 1 A
2 1 B
3 1 C
4 2 X
5 2 Y
6 2 Z
I would like the following result:
id group_id values
-- -------- ------
1 1 A
2 1 AB
3 1 ABC
4 2 X
5 2 XY
6 2 XYZ
Here is one option, using a correlated subquery to handle the rollup of the value column:
SELECT
t1.id,
t1.group_id,
(SELECT LISTAGG(t2.val, '') WITHIN GROUP (ORDER BY t2.id)
FROM yourTable t2
WHERE t1.group_id = t2.group_id AND t2.id <= t1.id) AS vals
FROM yourTable t1
ORDER BY
t1.id;
Demo
The logic here is that, for each group, with rollup a concatenation of all values coming at or before the current id value in a given row.
Another approach to this, one which might perform and scale better, would be to use a recursive CTE. But, that would take more code, and might be harder to digest than what I wrote above.
I have a table with 3 different columns pid,org,amount as shown below.
pid org amount
---- ---- ------
1 1 5
1 1 6
2 1 2
2 1 4
I need the records grouped by pid and org with the maximum amount.
As,Rich functionalities of sql are not supported in hive need an easy way of obtaining it.
The result table should be like
pid org amount
---- ---- ------
1 1 6
2 1 4
select pid,org,max(amount) from table1 group by pid,org;
use max function
Returns the maximum value of the column in the group
select pid,org,max(amount) from data
group by pid,org;
if not work, convert amount in double;
select pid,org,max(CAST(amount as double)) from data
group by pid,org;
How can one reference a calculated value from the previous row in a SQL query? In my case each row is an event that somehow manipulates the same value from the previous row.
The raw data looks like this:
Eventno Eventtype Totalcharge
3 ACQ 32
2 OUT NULL
1 OUT NULL
Lets say each Eventtype=OUT should half the previous row totalcharge in a column called Remaincharge:
Eventno Eventtype Totalcharge Remaincharge
3 ACQ 32 32
2 OUT NULL 16
1 OUT NULL 8
I've already tried the LAG analytic function but that does not allow me to get a calculated value from the previous row. Tried something like this:
LAG(remaincharge, 1, totalcharge) OVER (PARTITION BY ...) as remaincharge
But this didn't work because remaingcharge could not be found.
Any ideas how to achieve this? Would need a analytics function that can give me the the cumulative sum but given a function instead with access to the previous value.
Thank you in advance!
Update problem description
I'm afraid my example problem was to general, here is a better problem description:
What remains of totalcharge is decided by the ratio of outqty/(previous remainqty).
Eventno Eventtype Totalcharge Remainqty Outqty
4 ACQ 32 100 0
3 OTHER NULL 100 0
2 OUT NULL 60 40
1 OUT NULL 0 60
Eventno Eventtype Totalcharge Remainqty Outqty Remaincharge
4 ACQ 32 100 0 32
3 OTHER NULL 100 0 32 - (0/100 * 32) = 32
2 OUT NULL 60 40 32 - (40/100 * 32) = 12.8
1 OUT NULL 0 60 12.8 - (60/60 * 12.8) = 0
In your case you could work out the first value using the FIRST_VALUE() analytic function and the power of 2 that you have to divide by with RANK() in a sub-query and then use that. It's very specific to your example but should give you the general idea:
select eventno, eventtype, totalcharge
, case when eventtype <> 'OUT' then firstcharge
else firstcharge / power(2, "rank" - 1)
end as remaincharge
from ( select a.*
, first_value(totalcharge) over
( partition by 1 order by eventno desc ) as firstcharge
, rank() over ( partition by 1 order by eventno desc ) as "rank"
from the_table a
)
Here's a SQL Fiddle to demonstrate. I haven't partitioned by anything because you've got nothing in your raw data to partition by...
A variation on Ben's answer to use a windowing clause, which seems to take care of your updated requirements:
select eventno, eventtype, totalcharge, remainingqty, outqty,
initial_charge - case when running_outqty = 0 then 0
else (running_outqty / 100) * initial_charge end as remainingcharge
from (
select eventno, eventtype, totalcharge, remainingqty, outqty,
first_value(totalcharge) over (partition by null
order by eventno desc) as initial_charge,
sum(outqty) over (partition by null
order by eventno desc
rows between unbounded preceding and current row)
as running_outqty
from t42
);
Except it gives 19.2 instead of 12.8 for the third row, but that's what your formula suggests it should be:
EVENTNO EVENT TOTALCHARGE REMAININGQTY OUTQTY REMAININGCHARGE
---------- ----- ----------- ------------ ---------- ---------------
4 ACQ 32 100 0 32
3 OTHER 100 0 32
2 OUT 60 40 19.2
1 OUT 0 60 0
If I add another split so it goes from 60 to zero in two steps, with another non-OUT record in the mix too:
EVENTNO EVENT TOTALCHARGE REMAININGQTY OUTQTY REMAININGCHARGE
---------- ----- ----------- ------------ ---------- ---------------
6 ACQ 32 100 0 32
5 OTHER 100 0 32
4 OUT 60 40 19.2
3 OUT 30 30 9.6
2 OTHER 30 0 9.6
1 OUT 0 30 0
There's an assumption that the remaining quantity is consistent and you can effectively track a running total of what has gone before, but from the data you've shown that looks plausible. The inner query calculates that running total for each row, and the outer query does the calculation; that could be condensed but is hopefully clearer like this...
Ben's answer is the better one (will probably perform better) but you can also do it like this:
select t.*, (connect_by_root Totalcharge) / power (2,level-1) Remaincharge
from the_table t
start with EVENTTYPE = 'ACQ'
connect by prior eventno = eventno + 1;
I think it's easier to read
Here is a demo
I'm trying to write a query that will display the minimum value (lowest score) for each hole eliminating any duplicates. In other words, if the minimum score is 3 on hole_num 1 and there are two or more scores with 3, none of the rows corresponding to hole_num 1 should be returned. However, if there is only one value of 3 on hole_num 1 and it is the minimum value, the row should be returned. Here is what I was able to come up with... unfortunately I can't figure out how to remove the duplicates.
sample table:
player_id hole_num score
------------- ------------ -----
1 1 4
1 2 5
2 1 3
2 2 5
my query that gets the minimum score for each hole_num (but does not eliminate the row if it occurs more than once):
select. r.player_id, r.hole_num, r.score
from scorecard_test r
join (select hole_num,
min(score) best
from scorecard_test
group by hole_num) v on r.hole_num = v.hole_num
and r.score = v.best
produces the following output:
player_id hole_num score
---------- --------- -----
1 2 5
2 1 3
2 2 5
I'm trying to write a query that would only display the second row above (score=3) since 5 on hole_num 2 (although it is minimum) is a repeat. Any help would be greatly appreciated.
A MySQL specific solution is to add a GROUP BY and HAVING COUNT(*) = 1 to your current query:
SELECT r.player_id, r.hole_num, r.score
FROM scorecard_test r
JOIN
(
SELECT hole_num, MIN(score) best
FROM scorecard_test
GROUP BY hole_num
) v
ON r.hole_num = v.hole_num AND r.score = v.best
GROUP BY hole_num, score
HAVING COUNT(*) = 1
A solution that would work more generally is to add one more join to find the unique rows:
SELECT r1.player_id, r1.hole_num, r1.score
FROM scorecard_test r1
JOIN
(
SELECT hole_num, MIN(score) best
FROM scorecard_test
GROUP BY hole_num
) v
ON r1.hole_num = v.hole_num AND r1.score = v.best
LEFT JOIN scorecard_test r2
ON r1.hole_num = r2.hole_num AND r1.player_id != r2.player_id AND r1.score = r2.score
WHERE r2.player_id IS NULL
The result in both cases is this:
player_id hole_num score
---------- --------- -----
2 1 3
You might be looking for this: http://www.w3schools.com/sql/sql_distinct.asp
Doing SELECT DISTINCT ... should return a single row for all that are complete duplicates.