[英]Previous row end date as the next row start date in SQL
Need Some help Please,需要一些帮助请,
I have a Field called 'hist_lastupdated' that contains the last updated date of the modification of the price of a product.我有一个名为“hist_lastupdated”的字段,其中包含产品价格修改的最后更新日期。
Based in this field, i want to extract the start date and the end date of the modification.基于此字段,我想提取修改的开始日期和结束日期。
In fact i have this:事实上我有这个:
**Product_id , Price , hist_lastupdated**
284849 18.95 2015-05-29 00:53:55
284849 15.95 2015-08-14 01:04:46
284849 18.95 2016-06-11 00:50:31
284849 15.95 2016-08-24 00:45:11
And i want to get the result like that :我想得到这样的结果:
**Product_id , Price , hist_lastupdated ,start_date , End_date**
284849 18.95 2015-05-29 00:53:55 2014-05-01 00:00:00 2015-05-29 00:53:55
284849 15.95 2015-08-14 01:04:46 2015-05-29 00:53:55 2015-08-14 01:04:46
284849 18.95 2016-06-11 00:50:31 2015-08-14 01:04:46 2016-06-11 00:50:31
284849 15.95 2016-08-24 00:45:11 2016-06-11 00:50:31 2016-08-24 00:45:11
In two word, the start date is the end date of the previous line i have many product id两个字,开始日期是上一行的结束日期我有很多产品id
Something like this:像这样的东西:
select Product_id,
Price,
hist_lastupdated,
lag(hist_lastupdated) over (partition by product_id order by hist_lastupdated) as start_date,
hist_lastupdated as end_date
from the_table
You didn't explain where the start_date for the first column is calculated.您没有解释第一列的 start_date 是在哪里计算的。 If that is beginning of the month from
hist_lastupdated
you can do something like this:如果那是从
hist_lastupdated
开始的月初,您可以执行以下操作:
lag(hist_lastupdated, 1, date_trunc('month', hist_lastupdated)) over (...)
I'm not sure how you would do this with just SQL but if you're able to do a bit of scripting you can write up a quick program that goes something like this (pseudocode):我不确定您将如何仅使用 SQL 来执行此操作,但是如果您能够编写一些脚本,则可以编写一个类似于以下内容的快速程序(伪代码):
lines = execute(SELECT product_id, price, hist_lastupdated FROM ProductTable)
startDate = 00:00:00 2014-05-01
outputLines = []
for row in lines:
outLine = []
outline.append(row[0])
outline.append(row[1])
outline.append(row[2])
outline.append(startDate)
outline.append(row[2])
startDate = row[2]
#Now do what you want with the output you have in a nice list of lists in the format you need, insert into a different table, write to a file, whatever you want.
I would use one of these solutions with MS SQL Server.我会在 MS SQL Server 中使用这些解决方案之一。 Hopefully one of them will apply to your problem.
希望其中之一适用于您的问题。
Pure SQL statement would look like this:纯 SQL 语句如下所示:
select
t.product_id, t.price, s.start_date, t.end_date
from
product t
outer apply
(
select top 1
end_date start_date
from
product o
where
o.end_date < t.end_date
order by
o.end_date desc
) s
The cross apply for each record returned can be a performance problem even with good indexing.即使具有良好的索引,对返回的每条记录的交叉应用也可能是一个性能问题。
If your SQL server supports the LAG function:如果您的 SQL 服务器支持 LAG 功能:
select
t.product_id, t.price,
LAG(T.end_date) over (order by t.end_date),
t.end_date
from
product t
Or you may find a way to do the same thing with variables in an update statement to "remember" the value in the previously updated record like the T-SQL:或者您可能会找到一种方法对更新语句中的变量执行相同的操作,以“记住”先前更新记录中的值,如 T-SQL:
-- Insert the desired output into a table variable that also has a start_date field.
-- Be sure to insert the records ordered by the date value.
declare @output table (product_id int, price numeric(10,2), [start_date] datetime, [end_date] datetime)
insert @output (product_id, price, end_date)
select 1, 10, '1/1/2015'
union all select 2, 11, '2/1/2015'
union all select 3, 15, '3/1/2015'
union all select 4, 20, '4/1/2015'
order by 3
-- Update the start date using the end date from the previous record
declare @start_date datetime, @end_date datetime
update
@output
set
@start_date = @end_date,
@end_date = end_date,
start_date = @start_date
select * from @output
I don't think this technique is recommended by Microsoft, but it has served me well and worked consistently.我认为 Microsoft 不推荐这种技术,但它对我很有用并且一直有效。 I only used this technique with table variables.
我只对表变量使用了这种技术。 I would be less inclined to trust the update sequence of records in in an actual table.
我不太愿意相信实际表中记录的更新顺序。 Now I would use LAG() instead.
现在我会改用 LAG() 。
This is the solution that i find it,i wanted to work with the lag function but the result is not what i wanted to have.这是我找到的解决方案,我想使用滞后功能,但结果不是我想要的。
The solution :解决方案 :
WITH
price_table_1 as (
select
-1 + ROW_NUMBER() over (partition by t1.product_id,t1.id ,t1.channel_id) as rownum_w1,
t1.id,
t1.product_id,
t1.channel_id,
t1.member_id,
t1.quantity,
t1.price,
t1.promo_dt_start,
t1.promo_dt_end,
t1.hist_lastupdated
FROM dwh_prod.hist_prices t1
where t1.channel_id='1004' and t1.product_id = '5896' and t1.quantity = '1' and t1.promo_dt_start is null
order by t1.product_id,t1.channel_id,t1.hist_lastupdated
),price_table_2 as (
select
ROW_NUMBER() over (partition by t2.product_id,t2.id ,t2.channel_id) as rownum_w2,
t2.id,
t2.product_id,
t2.channel_id,
t2.member_id,
t2.quantity,
t2.price,
t2.promo_dt_start,
t2.promo_dt_end,
t2.hist_lastupdated
FROM dwh_prod.hist_prices t2
where t2.channel_id='1004' and t2.product_id = '5896' and t2.quantity = '1' and t2.promo_dt_start is null
order by t2.product_id,t2.channel_id,t2.hist_lastupdated
)
select
t1.id,
t1.product_id,
t1.channel_id,
t1.member_id,
t1.quantity,
t1.price,
t1.promo_dt_start,
t1.promo_dt_end,
t2.hist_lastupdated as start_date,
t1.hist_lastupdated as end_date
FROM price_table_1 t1
inner join price_table_2 t2
on t2.product_id = t1.product_id and t2.id = t1.id and t2.channel_id = t1.channel_id
and rownum_w1 = (rownum_w2)
UNION ALL
select
t1.id,
t1.product_id,
t1.channel_id,
t1.member_id,
t1.quantity,
t1.price,
t1.promo_dt_start,
t1.promo_dt_end,
CONVERT(TIMESTAMP,'2014-01-01') as start_date,
t1.hist_lastupdated as end_date
FROM price_table_1 t1
where rownum_w1 = '0';
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.