How to make a copy to previous value to another column - sql

I have a Postgres database which is have a tons of data and including schema and all database attributes. I want to create open price which is pulling from to same symbol previous close price.
My data is like:
ID DATE SYMBOL OPEN CLOSE
1 1.01.2020 ABC 2,33
2 1.01.2020 XYZ 10,32
3 1.01.2020 KLM 30,33
4 1.01.2020 DEF 50,78
5 3.01.2020 ABC 3,00
6 3.01.2020 KLM 31,00
7 4.01.2020 ABC 4,00
8 4.01.2020 XYZ 13,00
9 4.01.2020 KLM 25,00
10 4.01.2020 DEF 48,00
11 5.01.2020 XYZ 11,50
12 5.01.2020 DEF 47,53
13 7.01.2020 ABC 4,58
14 7.01.2020 XYZ 12,54
15 7.01.2020 KLM 25,78
16 7.01.2020 DEF 48,33
I created Open colum which is should be have previous symbol prices.
My expect output:
ID DATE SYMBOL OPEN CLOSE
1 01.01.2020 ABC 2,33
2 01.01.2020 XYZ 10,32
3 01.01.2020 KLM 30,33
4 01.01.2020 DEF 50,78
5 03.01.2020 ABC 2,33 3,00
6 03.01.2020 KLM 30,33 31,00
7 04.01.2020 ABC 3,00 4,00
8 04.01.2020 XYZ 10,32 13,00
9 04.01.2020 KLM 31,00 25,00
10 04.01.2020 DEF 50,78 48,00
11 05.01.2020 XYZ 13,00 11,50
12 05.01.2020 DEF 48,00 47,53
13 07.01.2020 ABC 4,00 4,58
14 07.01.2020 XYZ 11,50 12,54
15 07.01.2020 KLM 25,00 25,78
16 07.01.2020 DEF 47,53 48,33
Open value = Previous close price value
ABC 01.01.2020 close price 2,33 = ABC 03.01.2020 open price 2,33
My database is active and fetching new data everyday which should be OPEN column must be filled up with (same symbols) previous close price data.
All symbolms doesnt have a price in some day and its getting over 100.000+ column at this moment. I tried something with sql query but didnt figure out. Im kindly new as database query. As I can understand documentation the following definitions
So Can this be possible? If so, how? Thanks in advance..

I think you just want lag():
select t.*,
lag(close) over (partition by symbol order by date) as prev_close
from t;
If you want to update the value in the table, you can use join (after adding the column):
update t
set open = tt.prev_close
from (select t.*,
lag(close) over (partition by symbol order by date) as prev_close
from t
) tt
where tt.id = t.id and
tt.prev_close is distinct from t.open;

Related

Returning only most recent audit rows using concatenation of other columns to find the correct grouping [duplicate]

This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed 8 months ago.
I am stuck on what I thought would be a fairly straightforward query in SQL Server (I'm using 2018)
I have a table (AUDIT_TABLE) that I have read only access to which looks like this:
ID
DimensionA
DimensionB
DimensionC
Amount
UserID
Timestamp
1
ABC
DEF
GHI
100
Mark
2022/01/01 12:00:00
2
ABC
DEF
GHI
10
James
2022/01/01 06:00:00
3
ABC
DEF
GHI
250
Mark
2022/01/01 02:00:00
4
JKL
MNO
PQR
250
Bob
2022/01/01 13:00:00
5
JKL
MNO
PQR
100
Dave
2022/01/01 12:00:00
What I'm trying to find is the most recent entries in an audit table and the grouping needs to be determined by combining multiple columns. eg All rows where (Dimension A + Dimension B + Dimension C) are the same are considered to be the same record and we want to find the most recent entry to it. In the table above IDs 1, 2 & 3 are the same (ABC+DEF+GHI), and IDs 4 & 5 are the same (JKL+MNO+PQR).
So using the above example table I am trying to write a select statement to return this result:
Dimension A
Dimension B
Dimension C
Amount
UserID
Timestamp
ABC
DEF
GHI
100
Mark
2022/01/01 12:00:00
JKL
MNO
PQR
250
Bob
2022/01/01 13:00:00
I have tried this query (amongst many other combinations) and just can't get the result I'm after:
SELECT DimensionA, DimensionB, DimensionC, Amount,
UserID, Max(Timestamp), (DimensionA + DimensionB + DimensionC) AS POV
FROM AUDIT_TABLE
GROUP BY POV
Any help would be greatly appreciated.
Does this work?
select DimensionA,
DimensionB,
DimensionC,Amount,UserID,TimeStamp
from (select DimensionA,
DimensionB,
DimensionC,Amount,UserID,TimeStamp,
row_number() over(partition by DimensionA,DimensionB,DimensionC order by Timestamp desc) as rn
from AUDIT_TABLE ) as T
where rn = 1
DB<>Fiddle
Reference

Creating a new calculated column in SQL

Is there a way to find the solution so that I need for 2 days, there are 2 UD's because there are June 24 2 times and for the rest there are single days.
I am showing the expected output here:
Primary key UD Date
-------------------------------------------
1 123 2015-06-24 00:00:00.000
6 456 2015-06-24 00:00:00.000
2 123 2015-06-25 00:00:00.000
3 658 2015-06-26 00:00:00.000
4 598 2015-06-27 00:00:00.000
5 156 2015-06-28 00:00:00.000
No of times Number of days
-----------------------------
4 1
2 2
The logic is 4 users are there who used the application on 1 day and there are 2 userd who used the application on 2 days
You can use two levels of aggregation:
select cnt, count(*)
from (select date, count(*) as cnt
from t
group by date
) d
group by cnt
order by cnt desc;

Get today and previous available date data in a single row

I have following table data for processing.
SYMBOL DATE OPENVALUE CLOSEVALUE
-------------------------------------------------
ABC 2019-01-01 10 15
ABC 2019-01-02 17 19
ABC 2019-01-03 13 20
ABC 2019-01-04 18 30
ABC 2019-01-07 25 45
ABC 2019-01-08 40 50
I want to process and display information as follow
SYMBOL DATE OPENVALUE PREVDAYCLOSINGVALUE
--------------------------------------------------------------
ABC 2019-01-01 10 NA
ABC 2019-01-02 17 15
ABC 2019-01-03 13 19
ABC 2019-01-04 18 20
ABC 2019-01-07 25 30
ABC 2019-01-08 40 45
If anyone can help. I am facing problem with inner joining current date with previous available date data.
You are looking for lag():
select t.*,
lag(closevalue) over (partition by symbol order by date) as prev_closevalue
from t;
Use LAG().
The 3-argument form lets you specify a default value. I would not recommend 'NA', since it does not have the same datatype as the other values (which looks like positive integers), so I used -1.
SELECT
t.*,
LAG(OPENVALUE, 1, -1) OVER(PARTITION BY [SYMBOL] ORDER BY [DATE]) AS PREVDAYCLOSINGVALUE
FROM mytable t

Using sequences to create group ID

I'm attempting to create group_ids based on a set of item_ids. The only indication that the item_ids are part of a single group is the fact that item_ids are sequential. For example, based on the first two columns below, the output I want is the third:
item item_id group_id
ABC 282 2
ABC 283 2
ABC 284 2
ABC 285 2
ABC 051 3
ABC 052 3
ABC 189 4
ABC 231 5
ABC 232 5
ABC 233 5
ABC 234 5
ABC 247 6
ABC 248 6
ABC 249 6
ABC 250 6
ABC 091 7
ABC 092 7
The group_id doesn't necessarily have to be sequential itself, it only has to be unique. I attempted this with the following code:
create sequence seq
start with 1
minvalue 1
increment by 1
cache 20;
select seq.nextval from dual; --to initialize the sequence
select
item,
item_id,
case when diff = 1 then seq.currval else seq.nextval end group_id
from
(
select
item,
item_id,
(id - lag(id, 1, 0) over (order by 1) diff
from
(
select
item,
item_id
from
table
)
);
But get the following output:
item item_id group_id
ABC 282 2
ABC 283 3
ABC 284 4
ABC 285 5
ABC 051 6
ABC 052 7
ABC 189 8
ABC 231 9
ABC 232 10
ABC 233 11
ABC 234 12
ABC 247 13
ABC 248 14
ABC 249 15
ABC 250 16
ABC 091 17
ABC 092 18
When looking for the cause of the problem, I found an excellent explanation by user ShannonSeverance that details why my solution won't work. However, it didn't provide any suggestions on how to move forward.
Does anyone have any ideas?
You have a problem, because SQL tables are inherently unordered. The following "should" logically work, although it won't in practice:
select ii.*, (item_id - rownum) as grp_id
from item_ids ii;
A sequence of item_ids in order minus the row number is constant. You can use that for a group, at least for a given item. To handle multiple items, concatenate the values together:
select ii.*, item||'-'||(item_id - rownum) as grp_id
from item_ids ii;
To really make this work, you need to add an order by -- this guarantees the ordering of the results from the select. This might work, assuming that there are "holes" between the groups:
select ii.*, item||'-'||(item_id - rownum) as grp_id
from item_ids ii
order by item, item_id;
Otherwise, you need some other column to determine the proper ordering for the items.

I need to show the monthly inventory data

I have a table some thing like as follows for Inventory details.
InventoryTable.
InventoryTableID DateCreated quantity ItemName
-------------------------------------------------
1 2010-02-04 12 abc
2 2010-03-10 4 abc
3 2010-03-13 5 xyz
4 2010-03-13 19 def
5 2010-03-17 15 abc
6 2010-03-29 15 abc
7 2010-04-01 22 xyz
8 2010-04-13 5 abc
9 2010-04-15 6 def
from the above table if my admin wants to know the inventory details for month April 2010 (i.e. Apr 1st 2010 - Apr 30th 2010)
I need the output as shown below.
inventory as on Apr 1st 2010
ItemName Datecreated qty
----------------------------
abc 2010-03-29 15
xyz 2010-04-01 22
def 2010-03-13 19
inventory as on Apr 30th 2010
ItemName Datecreated qty
---------------------------
abc 2010-04-13 5
xyz 2010-04-01 22
def 2010-04-15 6
For your first result set, run with #YourDataParam = '2010-04-01'. For the second set, use '2010-04-30'.
;with cteMaxDate as (
select it.ItemName, max(it.DateCreated) as MaxDate
from InventoryTable it
where it.DateCreated <= #YourDataParam
group by it.ItemName
)
select it.ItemName, it.DateCreated, it.qty
from cteMaxDate c
inner join InventoryTable it
on c.ItemName = it.ItemName
and c.MaxDate = it.DateCreated