Sql Query in finding max value by comparing values - sql

I have a problem in finding the max value by comparing the values.
id
date
record
1
2022-01-01
100
2.
2022-01-02
10
3.
2022-01-03
5
4.
2022-01-04
20
5
2022-01-06
22
6
2022-01-10
30
and so on 1000+records
column "date" should compare first value with second value and get the max "record", and then second date with third date and should return the max value and so on
so the final result should return
100,10,20,22,30...
please help with sql query

I'm expressing the below in SQL - as it would work in any relational SQL database - I'm not sure if Spark's LEAD() function needs the OVER() clause or not, standard SQL does.
WITH
-- your input, names changed to avoid reserved words
indata(id,dt,rec) AS (
SELECT 1,DATE '2022-01-01',100
UNION ALL SELECT 2,DATE '2022-01-02',10
UNION ALL SELECT 3,DATE '2022-01-03',5
UNION ALL SELECT 4,DATE '2022-01-04',20
UNION ALL SELECT 5,DATE '2022-01-06',22
UNION ALL SELECT 6,DATE '2022-01-10',30
)
-- end of input, real query starts here ...
SELECT
*
, LEAD(rec) OVER(ORDER BY dt) as nextrec
, GREATEST(LEAD(rec) OVER(ORDER BY dt),rec) AS biggerofpair
FROM indata;
id
dt
rec
nextrec
biggerofpair
1
2022-01-01
100
10
100
2
2022-01-02
10
5
10
3
2022-01-03
5
20
20
4
2022-01-04
20
22
22
5
2022-01-06
22
30
30
6
2022-01-10
30
(null)
(null)

Related

combine two table with different content to make a table where each id has two rows in bigquery

hope you can help me with this. so i have one table that contains value
user_id
Monday.
Tuesday
Wednesday
aa11
100
164
284
bb22.
223
143
346
and another table that contains count
user_id
Monday.
Tuesday
Wednesday
aa11
2
3
4
bb22
5
2
3
how can i combine both so it looks like this?
user_id
type
Monday.
Tuesday
Wednesday
aa11
value
100
164
284
aa11
count
2
3
4
bb22.
value
223
143
346
bb22
count
5
2
3
is it even a good practice to pivot long like this or should i just pivot wide so there would be columns monday_value, monday_count, tuesday_value, tuesday_count, etc?
Simple union? :
select * from (
select user_id, 'value' as type,Monday.,Tuesday,Wednesday
from table1
union all
select user_id, 'count' as type,Monday.,Tuesday,Wednesday
from table2
) t
You can use simple way as given in answer by #eshirvana.
Or as per your ask, if you want to do it horizontally you can do it following way:
WITH week_value AS
(
SELECT 1 as user, 100 as monday
UNION ALL SELECT 2 as user, 200 as monday
),
week_count as (
SELECT 1 as user, 10 as monday
UNION ALL SELECT 2 as user, 2 as monday
)
select A.user, A.monday as monday_value, B.monday as monday_count
from week_value as A
FULL JOIN week_count as B on A.user = B.user

Get the latest price SQLITE

I have a table which contain _id, underSubheadId, wefDate, price.
Whenever a product is created or price is edited an entry is made in this table also.
What I want is if I enter a date, I get the latest price of all distinct UnderSubheadIds before the date (or on that date if no entry found)
_id underHeadId wefDate price
1 1 2016-11-01 5
2 2 2016-11-01 50
3 1 2016-11-25 500
4 3 2016-11-01 20
5 4 2016-11-11 30
6 5 2016-11-01 40
7 3 2016-11-20 25
8 5 2016-11-15 52
If I enter 2016-11-20 as date I should get
1 5
2 50
3 25
4 30
5 52
I have achieved the result using ROW NUMBER function in SQL SERVER, but I want this result in Sqlite which don't have such function.
Also if a date like 2016-10-25(which have no entries) is entered I want the price of the date which is first.
Like for 1 we will get price as 5 as the nearest and the 1st entry is 2016-11-01.
This is the query for SQL SERVER which is working fine. But I want it for Sqlite which don't have ROW_NUMBER function.
select underSubHeadId,price from(
select underSubHeadId,price, ROW_NUMBER() OVER (Partition By underSubHeadId order by wefDate desc) rn from rates
where wefDate<='2016-11-19') newTable
where newTable.rn=1
Thank You
This is a little tricky, but here is one way:
select t.*
from t
where t.wefDate = (select max(t2.wefDate)
from t t2
where t2.underSubHeadId = t.underSubHeadId and
t2.wefdate <= '2016-11-20'
);
select underHeadId, max(price)
from t
where wefDate <= "2016-11-20"
group by underHead;

Possible recursive or analytical query. Can this be done via SQL or is a Script Required?

Not sure if this is possible or not through a standard query but here is how I would like my data to be.
START END SETTLE NEW_SETTLE CORRECTION_FACT STORED_SETTLE
1 2 120 NULL 1 120
2 3 127 119 1.0084 128.0668
3 4 NULL 125 1.0245344 NULL
Calculations are done as follows:
CORRECTION_FACT
Basically, if NEW SETTLE is null or this is Row 1 than correction factor is always 1. If row > 1 than correction factor is PREV ROW STORED_SETTLE / NEW_SETTLE eg. 120/119
STORED_SETTLE
This will always be CORRECTION_FACTOR * SETTLE. This value is not known until the next row is inserted so there will be times where it is NULL. Tricky part is that this is dependent on CORRECTION_FACT which is also a calculated value and CORRECTION_FACT is dependent on STORED_SETTLE.
In terms of values that I have, I have SETTLE, NEW_SETTLE, START and END. CORRECTION_FACT and STORED_SETTLE will always have to be calculated.
So the question here is can I do this with some sort of recursive query or analytical function or do I have to write a script to populate?
with T1 as
(select 1 strt, 2 en, 120 settle, null new_settle from dual union all
select 2 strt, 3 en, 127 settle, 119 new_settle from dual union all
select 3 strt, 4 en, null settle, 125 new_settle from dual
)
select strt
, en
, settle
, new_settle
, correction_fact
, stored_settle
from t1
model
dimension by(row_number() over (order by strt) RowNumber)
measures(strt, en, settle, new_settle
, cast(null as number) correction_fact
, cast(null as number) stored_settle)
rules automatic order
(
correction_fact[1]=1,
correction_fact[RowNumber>1] = decode(new_settle[cv()], null,
1,stored_settle[cv()-1]/new_settle[cv()]),
stored_settle[rownumber]=(correction_fact[cv()]*settle[cv()])
);
Result:
STRT EN SETTLE NEW_SETTLE CORRECTION_FACT STORED_SETTLE
---------- ---------- ---------- ---------- --------------- -------------
1 2 120 1 120
2 3 127 119 1.00840336 128.067227
3 4 125 1.02453782

Update the list of dates to have the same day

I have this in my table
TempTable
Id Date
1 1-15-2010
2 2-14-2010
3 3-14-2010
4 4-15-2010
i would like to change every record so that they have all same day, that is the 15th
like this
TempTable
Id Date
1 1-15-2010
2 2-15-2010 <--change to 15
3 3-15-2010 <--change to 15
4 4-15-2010
what if i like on the 30th?
the records should be
TempTable
Id Date
1 1-30-2010
2 2-28-2010 <--change to 28 because feb has 28 days only
3 3-30-2010 <--change to 30
4 4-30-2010
thanks
You can play some fun tricks with DATEADD/DATEDIFF:
create table T (
ID int not null,
DT date not null
)
insert into T (ID,DT)
select 1,'20100115' union all
select 2,'20100214' union all
select 3,'20100314' union all
select 4,'20100415'
SELECT ID,DATEADD(month,DATEDIFF(month,'20100101',DT),'20100115')
from T
SELECT ID,DATEADD(month,DATEDIFF(month,'20100101',DT),'20100130')
from T
Results:
ID
----------- -----------------------
1 2010-01-15 00:00:00.000
2 2010-02-15 00:00:00.000
3 2010-03-15 00:00:00.000
4 2010-04-15 00:00:00.000
ID
----------- -----------------------
1 2010-01-30 00:00:00.000
2 2010-02-28 00:00:00.000
3 2010-03-30 00:00:00.000
4 2010-04-30 00:00:00.000
Basically, in the DATEADD/DATEDIFF, you specify the same component to both (i.e. month). Then, the second date constant (i.e. '20100130') specifies the "offset" you wish to apply from the first date (i.e. '20100101'), which will "overwrite" the portion of the date your not keeping. My usual example is when wishing to remove the time portion from a datetime value:
SELECT DATEADD(day,DATEDIFF(day,'20010101',<date column>),'20100101')
You can also try something like
UPDATE TempTable
SET [Date] = DATEADD(dd,15-day([Date]), DATEDIFF(dd,0,[Date]))
We have a function that calculates the first day of a month, so I just addepted it to calculate the 15 instead...

Can I use Oracle SQL to plot actual dates from Schedule Information?

I asked this question in regard to SQL Server, but what's the answer for an Oracle environment (10g)?
If I have a table containing schedule information that implies particular dates, is there a SQL statement that can be written to convert that information into actual rows, using something like MSSQL's Commom Table Expressions, perhaps?
Consider a payment schedule table with these columns:
StartDate - the date the schedule begins (1st payment is due on this date)
Term - the length in months of the schedule
Frequency - the number of months between recurrences
PaymentAmt - the payment amount :-)
SchedID StartDate Term Frequency PaymentAmt
-------------------------------------------------
1 05-Jan-2003 48 12 1000.00
2 20-Dec-2008 42 6 25.00
Is there a single SQL statement to allow me to go from the above to the following?
Running
SchedID Payment Due Expected
Num Date Total
--------------------------------------
1 1 05-Jan-2003 1000.00
1 2 05-Jan-2004 2000.00
1 3 05-Jan-2005 3000.00
1 4 05-Jan-2006 4000.00
2 1 20-Dec-2008 25.00
2 2 20-Jun-2009 50.00
2 3 20-Dec-2009 75.00
2 4 20-Jun-2010 100.00
2 5 20-Dec-2010 125.00
2 6 20-Jun-2011 150.00
2 7 20-Dec-2011 175.00
Your thoughts are appreciated.
Oracle actually has syntax for hierarchical queries using the CONNECT BY clause. SQL Server's use of the WITH clause looks like a hack in comparison:
SELECT t.SchedId,
CASE LEVEL
WHEN 1 THEN
t.StartDate
ELSE
ADD_MONTHS(t.StartDate, t.frequency)
END 'DueDate',
CASE LEVEL
WHEN 1 THEN
t.PaymentAmt
ELSE
SUM(t.paymentAmt)
END 'RunningExpectedTotal'
FROM PaymentScheduleTable t
WHERE t.PaymentNum <= t.Term / t.Frequency
CONNECT BY PRIOR t.startdate = t.startdate
GROUP BY t.schedid, t.startdate, t.frequency, t.paymentamt
ORDER BY t.SchedId, t.PaymentNum
I'm not 100% on that - I'm more confident about using:
SELECT t.SchedId,
t.StartDate 'DueDate',
t.PaymentAmt 'RunningExpectedTotal'
FROM PaymentScheduleTable t
WHERE t.PaymentNum <= t.Term / t.Frequency
CONNECT BY PRIOR t.startdate = t.startdate
ORDER BY t.SchedId, t.PaymentNum
...but it doesn't include the logic to handle when you're dealing with the 2nd+ entry in the chain to add months & sum the amounts. The summing could be done with GROUP BY CUBE or ROLLUP depending on the detail needed.
I don't understand why 5 payment days for schedid = 1 and 7 for scheid = 2?
48 /12 = 4 and 42 / 6 = 7. So I expected 4 payment days for schedid = 1.
Anyway I use the model clause:
create table PaymentScheduleTable
( schedid number(10)
, startdate date
, term number(3)
, frequency number(3)
, paymentamt number(5)
);
insert into PaymentScheduleTable
values (1,to_date('05-01-2003','dd-mm-yyyy')
, 48
, 12
, 1000);
insert into PaymentScheduleTable
values (2,to_date('20-12-2008','dd-mm-yyyy')
, 42
, 6
, 25);
commit;
And now the select with model clause:
select schedid, to_char(duedate,'dd-mm-yyyy') duedate, expected, i paymentnum
from paymentscheduletable
model
partition by (schedid)
dimension by (1 i)
measures (
startdate duedate
, paymentamt expected
, term
, frequency)
rules
( expected[for i from 1 to term[1]/frequency[1] increment 1]
= nvl(expected[cv()-1],0) + expected[1]
, duedate[for i from 1 to term[1]/frequency[1] increment 1]
= add_months(duedate[1], (cv(i)-1) * frequency[1])
)
order by schedid,i;
This outputs:
SCHEDID DUEDATE EXPECTED PAYMENTNUM
---------- ---------- ---------- ----------
1 05-01-2003 1000 1
1 05-01-2004 2000 2
1 05-01-2005 3000 3
1 05-01-2006 4000 4
2 20-12-2008 25 1
2 20-06-2009 50 2
2 20-12-2009 75 3
2 20-06-2010 100 4
2 20-12-2010 125 5
2 20-06-2011 150 6
2 20-12-2011 175 7
11 rows selected.
I didn't set out to answer my own question, but I'm doing work with Oracle now and I have had to learn some new Oracle-flavored things.
Anyway, the CONNECT BY statement is really nice--yes, much nicer than MSSQL's hierchical query approach, and using that construct, I was able to produce a very clean query that does what I was looking for:
SELECT DISTINCT
t.SchedID
,level as PaymentNum
,add_months(T.StartDate,level - 1) as DueDate
,(level * t.PaymentAmt) as RunningTotal
FROM SchedTest t
CONNECT BY level <= (t.Term / t.Frequency)
ORDER BY t.SchedID, level
My only remaining issue is that I had to use DISTINCT because I couldn't figure out how to select my rows from DUAL (the affable one-row Oracle table) instead of from my table of schedule data, which has at least 2 rows. If I could do the above with FROM DUAL, then my DISTINCT indicator wouldn't be necessary. Any thoughts?
Other than that, I think this is pretty nice. Et tu?