|
database
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Get last date in result setI need to get the last date of when stock levels hit zero so I can then do a datediff to calcualte days out of stock. Here is a table with sample data productid,stocklevel,date 1,10,1/1/2006 1,0,2/1/2006 1,0,3/1/2006 1,100,3/1/2006 2,0,1/1/2006 2,0,2/1/2006 2,10,3/1/2006 Desired result productid,stocklevel,date,lastdateoutofstock 1,10,1/1/2006,null 1,0,2/1/2006,2/1/2006 1,0,3/1/2006 ,2/1/2006 1,100,3/1/2006,NULL 1,0,4/1/2006,4/1/2006 2,0,1/1/2006 ,1/1/2006 2,0,2/1/2006 ,1/1/2006 2,10,3/1/2006,NULL Currently I use a cursor to do this but it is taking too long. Hoping it can be done using Set based T-SQL. Thanks Requirement not clear boss///
Seems like you need to take previous out of stock date whenever a out of stock record comes. But ur example is not that helpful. But guessing I think you can rely only looping and take it. How much is the record size. If its not much try in table variable and try cutting cursor and optimize it. -- Thanks, Sree [Please specify the version of Sql Server as we can save one thread and time asking back if its 2000 or 2005] Show quote "kis***@microlytics.co.uk" wrote: > Hi, > > I need to get the last date of when stock levels hit zero so I can then > do a datediff to calcualte days out of stock. Here is a table with > sample data > > productid,stocklevel,date > 1,10,1/1/2006 > 1,0,2/1/2006 > 1,0,3/1/2006 > 1,100,3/1/2006 > 2,0,1/1/2006 > 2,0,2/1/2006 > 2,10,3/1/2006 > > Desired result > > productid,stocklevel,date,lastdateoutofstock > 1,10,1/1/2006,null > 1,0,2/1/2006,2/1/2006 > 1,0,3/1/2006 ,2/1/2006 > 1,100,3/1/2006,NULL > 1,0,4/1/2006,4/1/2006 > 2,0,1/1/2006 ,1/1/2006 > 2,0,2/1/2006 ,1/1/2006 > 2,10,3/1/2006,NULL > > Currently I use a cursor to do this but it is taking too long. Hoping > it can be done using Set based T-SQL. > > Thanks > > Thanks for the response
To clarify, based on the sample data when stocklevel is zero then we take the date of that record if it has not been out of stock the day before. This would become the lastdateoutofstock. If that same product has further stocklevels of zero in the subsequant records then we take the first date out of stock. Looking at the sample output data product 1 goes out of stock on 2/1/2006 and is out of stock until 3/1/2006 so the lastdateoutofstock should be 2/1/2006. It then goes out of stock again on 4/1/2006 so we set lastdateoutofstock to 4/1/2006 since this is the first date of when it went out of stock after stock was replenished. We have around 55 million records that need to be loaded historically and the cursor compares first record to previous record and is currently taking around 12 hours to run. Could this be done using set based SQL . Using SQL 2000 Thanks productid,stocklevel,date,lastdateoutofstock 1,10,1/1/2006,null 1,0,2/1/2006,2/1/2006 1,0,3/1/2006 ,2/1/2006 1,100,4/1/2006,NULL 1,0,4/1/2006,4/1/2006 2,0,1/1/2006 ,1/1/2006 2,0,2/1/2006 ,1/1/2006 2,10,3/1/2006,NULL Sreejith G wrote: Show quote > Requirement not clear boss/// > > Seems like you need to take previous out of stock date whenever a out of > stock record comes. But ur example is not that helpful. > > But guessing I think you can rely only looping and take it. How much is the > record size. If its not much try in table variable and try cutting cursor and > optimize it. > > -- > Thanks, > Sree > [Please specify the version of Sql Server as we can save one thread and time > asking back if its 2000 or 2005] > > > > "kis***@microlytics.co.uk" wrote: > > > Hi, > > > > I need to get the last date of when stock levels hit zero so I can then > > do a datediff to calcualte days out of stock. Here is a table with > > sample data > > > > productid,stocklevel,date > > 1,10,1/1/2006 > > 1,0,2/1/2006 > > 1,0,3/1/2006 > > 1,100,3/1/2006 > > 2,0,1/1/2006 > > 2,0,2/1/2006 > > 2,10,3/1/2006 > > > > Desired result > > > > productid,stocklevel,date,lastdateoutofstock > > 1,10,1/1/2006,null > > 1,0,2/1/2006,2/1/2006 > > 1,0,3/1/2006 ,2/1/2006 > > 1,100,3/1/2006,NULL > > 1,0,4/1/2006,4/1/2006 > > 2,0,1/1/2006 ,1/1/2006 > > 2,0,2/1/2006 ,1/1/2006 > > 2,10,3/1/2006,NULL > > > > Currently I use a cursor to do this but it is taking too long. Hoping > > it can be done using Set based T-SQL. > > > > Thanks > > > > Try this (untested, since you haven't posted any DDL):
select currStock.productid ,currStock.stocklevel ,currStock.date ,lastdateoutofstock = case when exists( select * from <table> prevStock where (prevStock.stocklevel = 0) and (prevStock.date <= currStock.date) ) then ( select top 1 prevStock.date from <table> prevStock where (prevStock.stocklevel = 0) and (prevStock.date <= currStock.date) order by prevStock.date desc ) end from <table> currStock ML --- http://milambda.blogspot.com/ On second thought that DESC ought to be ASC. Well, you'll be the judge of
that. ML --- http://milambda.blogspot.com/ Hi ML,
What would you suggest indexing on the table mentioned based on your query? Hopefully I can get some performance improvements on indexing as well. Thanks ML wrote: Show quote > On second thought that DESC ought to be ASC. Well, you'll be the judge of > that. > > > ML > > --- > http://milambda.blogspot.com/ Perhaps a covering index on (date, productid, stocklevel). Just judging from
this one query. But - does the query work as it's supposed to? ML --- http://milambda.blogspot.com/ Hi ML,
I've just tested it on the large table but got back incorrect results. I then tested the SQL on a sample data (DDL below for your information) It appears that lastdayoutofstock is defaulting on the first date in the table rather than getting the true last date out of stock for a particuar product. Thanks for your help by the way. Much appreciated. ---------------------------------------------------------------------- CREATE TABLE [stock] ( [productid] [int] NULL , [stocklevel] [int] NULL , [date] [datetime] NULL ) ON [PRIMARY] GO insert into stock(productid ,stocklevel ,date ) values (1,10,'1/1/2006') insert into stock(productid ,stocklevel ,date ) values (1,0,'2/1/2006') insert into stock(productid ,stocklevel ,date ) values (1,0,'3/1/2006') insert into stock(productid ,stocklevel ,date ) values (1,100,'4/1/2006') insert into stock(productid ,stocklevel ,date ) values (2,0,'1/1/2006') insert into stock(productid ,stocklevel ,date ) values (2,0,'2/1/2006') insert into stock(productid ,stocklevel ,date ) values (2,10,'3/1/2006') ML wrote: Show quote > Perhaps a covering index on (date, productid, stocklevel). Just judging from > this one query. > > But - does the query work as it's supposed to? > > > ML > > --- > http://milambda.blogspot.com/ Hi ML.
Just modified your original sql by adding the productid constraint in the where clause of the select statement. SQL below does the trick. Thanks again for valuable time and input. select currStock.productid ,currStock.stocklevel ,currStock.[date] ,lastdateoutofstock = case when exists( select * from stock prevStock where (prevStock.stocklevel = 0) and (prevStock.[date] <= currStock.[date]) and (prevstock.productid = currstock.productid)and (currstock.stocklevel =0) ) then ( select top 1 prevStock.[date] from stock prevStock where (prevStock.stocklevel = 0) and (prevStock.[date] <= currStock.[date]) and (prevstock.productid = currstock.productid) order by prevStock.[date] Asc ) end from stock currStock kis***@microlytics.co.uk wrote: Show quote > Hi ML, > > I've just tested it on the large table but got back incorrect results. > I then tested the SQL on a sample data (DDL below for your information) > > It appears that lastdayoutofstock is defaulting on the first date in > the table rather than getting the true last date out of stock for a > particuar product. > > Thanks for your help by the way. Much appreciated. > > ---------------------------------------------------------------------- > CREATE TABLE [stock] ( > [productid] [int] NULL , > [stocklevel] [int] NULL , > [date] [datetime] NULL > ) ON [PRIMARY] > GO > > > insert into stock(productid ,stocklevel ,date ) values > (1,10,'1/1/2006') > insert into stock(productid ,stocklevel ,date ) values > (1,0,'2/1/2006') > insert into stock(productid ,stocklevel ,date ) values > (1,0,'3/1/2006') > insert into stock(productid ,stocklevel ,date ) values > (1,100,'4/1/2006') > insert into stock(productid ,stocklevel ,date ) values > (2,0,'1/1/2006') > insert into stock(productid ,stocklevel ,date ) values > (2,0,'2/1/2006') > insert into stock(productid ,stocklevel ,date ) values > (2,10,'3/1/2006') > > ML wrote: > > Perhaps a covering index on (date, productid, stocklevel). Just judging from > > this one query. > > > > But - does the query work as it's supposed to? > > > > > > ML > > > > --- > > http://milambda.blogspot.com/ You can try this.....
select s1.ProductId,s1.stocklevel,s1.date1, (select min(s2.date1) from stock s2 where s1.ProductId = s2.ProductId and s2.date1 <= s1.date1 and s2.stocklevel =0 and s1.stocklevel = 0 and s2.date1 >= (select max(s3.date1) from stock s3 where s3.date1 <= s1.date1 and s3.stocklevel <> 0 ) ) from stock s1 order by 1,3 - Sha Anand Show quote "kis***@microlytics.co.uk" wrote: > Hi ML. > > Just modified your original sql by adding the productid constraint in > the where clause of the select statement. SQL below does the trick. > > Thanks again for valuable time and input. > > > select currStock.productid > ,currStock.stocklevel > ,currStock.[date] > ,lastdateoutofstock > = case > when exists( > select * > from stock prevStock > where > (prevStock.stocklevel > = 0) > and > (prevStock.[date] <= currStock.[date]) and (prevstock.productid = > currstock.productid)and > (currstock.stocklevel =0) > ) > then ( > select top 1 prevStock.[date] > from stock prevStock > where > (prevStock.stocklevel > = 0) > and > (prevStock.[date] <= currStock.[date]) > and (prevstock.productid = currstock.productid) > order by > prevStock.[date] Asc > ) > end > from stock currStock > > > > kis***@microlytics.co.uk wrote: > > Hi ML, > > > > I've just tested it on the large table but got back incorrect results. > > I then tested the SQL on a sample data (DDL below for your information) > > > > It appears that lastdayoutofstock is defaulting on the first date in > > the table rather than getting the true last date out of stock for a > > particuar product. > > > > Thanks for your help by the way. Much appreciated. > > > > ---------------------------------------------------------------------- > > CREATE TABLE [stock] ( > > [productid] [int] NULL , > > [stocklevel] [int] NULL , > > [date] [datetime] NULL > > ) ON [PRIMARY] > > GO > > > > > > insert into stock(productid ,stocklevel ,date ) values > > (1,10,'1/1/2006') > > insert into stock(productid ,stocklevel ,date ) values > > (1,0,'2/1/2006') > > insert into stock(productid ,stocklevel ,date ) values > > (1,0,'3/1/2006') > > insert into stock(productid ,stocklevel ,date ) values > > (1,100,'4/1/2006') > > insert into stock(productid ,stocklevel ,date ) values > > (2,0,'1/1/2006') > > insert into stock(productid ,stocklevel ,date ) values > > (2,0,'2/1/2006') > > insert into stock(productid ,stocklevel ,date ) values > > (2,10,'3/1/2006') > > > > ML wrote: > > > Perhaps a covering index on (date, productid, stocklevel). Just judging from > > > this one query. > > > > > > But - does the query work as it's supposed to? > > > > > > > > > ML > > > > > > --- > > > http://milambda.blogspot.com/ > > small correction... use the following Query
select s1.ProductId,s1.stocklevel,s1.[date], (select min(s2.[date]) from stock s2 where s1.ProductId = s2.ProductId and s2.[date] <= s1.[date] and s2.stocklevel =0 and s1.stocklevel = 0 and s2.[date] >= ISNULL((select max(s3.[date]) from stock s3 where s3.[date] < s1.[date] and s3.stocklevel <> 0 ),s1.[date]) ) from stock s1 order by 1,3 - Sha Anand Show quote "Sha Anand" wrote: > You can try this..... > > select s1.ProductId,s1.stocklevel,s1.date1, > (select min(s2.date1) from stock s2 > where > s1.ProductId = s2.ProductId and > s2.date1 <= s1.date1 and > s2.stocklevel =0 and s1.stocklevel = 0 and > s2.date1 >= > (select max(s3.date1) from stock s3 where s3.date1 <= s1.date1 and > s3.stocklevel <> 0 ) > ) > from stock s1 > order by 1,3 > > - Sha Anand > > "kis***@microlytics.co.uk" wrote: > > > Hi ML. > > > > Just modified your original sql by adding the productid constraint in > > the where clause of the select statement. SQL below does the trick. > > > > Thanks again for valuable time and input. > > > > > > select currStock.productid > > ,currStock.stocklevel > > ,currStock.[date] > > ,lastdateoutofstock > > = case > > when exists( > > select * > > from stock prevStock > > where > > (prevStock.stocklevel > > = 0) > > and > > (prevStock.[date] <= currStock.[date]) and (prevstock.productid = > > currstock.productid)and > > (currstock.stocklevel =0) > > ) > > then ( > > select top 1 prevStock.[date] > > from stock prevStock > > where > > (prevStock.stocklevel > > = 0) > > and > > (prevStock.[date] <= currStock.[date]) > > and (prevstock.productid = currstock.productid) > > order by > > prevStock.[date] Asc > > ) > > end > > from stock currStock > > > > > > > > kis***@microlytics.co.uk wrote: > > > Hi ML, > > > > > > I've just tested it on the large table but got back incorrect results. > > > I then tested the SQL on a sample data (DDL below for your information) > > > > > > It appears that lastdayoutofstock is defaulting on the first date in > > > the table rather than getting the true last date out of stock for a > > > particuar product. > > > > > > Thanks for your help by the way. Much appreciated. > > > > > > ---------------------------------------------------------------------- > > > CREATE TABLE [stock] ( > > > [productid] [int] NULL , > > > [stocklevel] [int] NULL , > > > [date] [datetime] NULL > > > ) ON [PRIMARY] > > > GO > > > > > > > > > insert into stock(productid ,stocklevel ,date ) values > > > (1,10,'1/1/2006') > > > insert into stock(productid ,stocklevel ,date ) values > > > (1,0,'2/1/2006') > > > insert into stock(productid ,stocklevel ,date ) values > > > (1,0,'3/1/2006') > > > insert into stock(productid ,stocklevel ,date ) values > > > (1,100,'4/1/2006') > > > insert into stock(productid ,stocklevel ,date ) values > > > (2,0,'1/1/2006') > > > insert into stock(productid ,stocklevel ,date ) values > > > (2,0,'2/1/2006') > > > insert into stock(productid ,stocklevel ,date ) values > > > (2,10,'3/1/2006') > > > > > > ML wrote: > > > > Perhaps a covering index on (date, productid, stocklevel). Just judging from > > > > this one query. > > > > > > > > But - does the query work as it's supposed to? > > > > > > > > > > > > ML > > > > > > > > --- > > > > http://milambda.blogspot.com/ > > > > Your method has 12 logical reads, mine has 2. I suspect mine offers better
performance:) -- Show quoteHilary Cotter Director of Text Mining and Database Strategy RelevantNOISE.Com - Dedicated to mining blogs for business intelligence. This posting is my own and doesn't necessarily represent RelevantNoise's positions, strategies or opinions. Looking for a SQL Server replication book? http://www.nwsu.com/0974973602.html Looking for a FAQ on Indexing Services/SQL FTS http://www.indexserverfaq.com "Sha Anand" <ShaAn***@discussions.microsoft.com> wrote in message news:7A96E73D-65A0-414E-9659-04AE76F5FD4C@microsoft.com... > small correction... use the following Query > > select s1.ProductId,s1.stocklevel,s1.[date], > (select min(s2.[date]) from stock s2 > where > s1.ProductId = s2.ProductId and > s2.[date] <= s1.[date] and > s2.stocklevel =0 and s1.stocklevel = 0 and > s2.[date] >= > ISNULL((select max(s3.[date]) from stock s3 where s3.[date] < s1.[date] > and > s3.stocklevel <> 0 ),s1.[date]) > ) > from stock s1 > order by 1,3 > > - Sha Anand > > "Sha Anand" wrote: > >> You can try this..... >> >> select s1.ProductId,s1.stocklevel,s1.date1, >> (select min(s2.date1) from stock s2 >> where >> s1.ProductId = s2.ProductId and >> s2.date1 <= s1.date1 and >> s2.stocklevel =0 and s1.stocklevel = 0 and >> s2.date1 >= >> (select max(s3.date1) from stock s3 where s3.date1 <= s1.date1 and >> s3.stocklevel <> 0 ) >> ) >> from stock s1 >> order by 1,3 >> >> - Sha Anand >> >> "kis***@microlytics.co.uk" wrote: >> >> > Hi ML. >> > >> > Just modified your original sql by adding the productid constraint in >> > the where clause of the select statement. SQL below does the trick. >> > >> > Thanks again for valuable time and input. >> > >> > >> > select currStock.productid >> > ,currStock.stocklevel >> > ,currStock.[date] >> > ,lastdateoutofstock >> > = case >> > when exists( >> > select * >> > from stock prevStock >> > where >> > (prevStock.stocklevel >> > = 0) >> > and >> > (prevStock.[date] <= currStock.[date]) and (prevstock.productid = >> > currstock.productid)and >> > (currstock.stocklevel =0) >> > ) >> > then ( >> > select top 1 prevStock.[date] >> > from stock prevStock >> > where >> > (prevStock.stocklevel >> > = 0) >> > and >> > (prevStock.[date] <= currStock.[date]) >> > and (prevstock.productid = currstock.productid) >> > order by >> > prevStock.[date] Asc >> > ) >> > end >> > from stock currStock >> > >> > >> > >> > kis***@microlytics.co.uk wrote: >> > > Hi ML, >> > > >> > > I've just tested it on the large table but got back incorrect >> > > results. >> > > I then tested the SQL on a sample data (DDL below for your >> > > information) >> > > >> > > It appears that lastdayoutofstock is defaulting on the first date in >> > > the table rather than getting the true last date out of stock for a >> > > particuar product. >> > > >> > > Thanks for your help by the way. Much appreciated. >> > > >> > > ---------------------------------------------------------------------- >> > > CREATE TABLE [stock] ( >> > > [productid] [int] NULL , >> > > [stocklevel] [int] NULL , >> > > [date] [datetime] NULL >> > > ) ON [PRIMARY] >> > > GO >> > > >> > > >> > > insert into stock(productid ,stocklevel ,date ) values >> > > (1,10,'1/1/2006') >> > > insert into stock(productid ,stocklevel ,date ) values >> > > (1,0,'2/1/2006') >> > > insert into stock(productid ,stocklevel ,date ) values >> > > (1,0,'3/1/2006') >> > > insert into stock(productid ,stocklevel ,date ) values >> > > (1,100,'4/1/2006') >> > > insert into stock(productid ,stocklevel ,date ) values >> > > (2,0,'1/1/2006') >> > > insert into stock(productid ,stocklevel ,date ) values >> > > (2,0,'2/1/2006') >> > > insert into stock(productid ,stocklevel ,date ) values >> > > (2,10,'3/1/2006') >> > > >> > > ML wrote: >> > > > Perhaps a covering index on (date, productid, stocklevel). Just >> > > > judging from >> > > > this one query. >> > > > >> > > > But - does the query work as it's supposed to? >> > > > >> > > > >> > > > ML >> > > > >> > > > --- >> > > > http://milambda.blogspot.com/ >> > >> > He wants the following results
1 10 2006-01-01 00:00:00.000 NULL 1 0 2006-02-01 00:00:00.000 2006-02-01 00:00:00.000 1 0 2006-03-01 00:00:00.000 2006-02-01 00:00:00.000 1 100 2006-04-01 00:00:00.000 NULL 1 0 2006-05-01 00:00:00.000 2006-05-01 00:00:00.000 2 0 2006-01-01 00:00:00.000 2006-01-01 00:00:00.000 2 0 2006-02-01 00:00:00.000 2006-01-01 00:00:00.000 2 10 2006-03-01 00:00:00.000 NULL But your query returns just 2 rows 1 2006-02-01 00:00:00.000 2006-05-01 00:00:00.000 2 2006-01-01 00:00:00.000 2006-02-01 00:00:00.000 - Sha Anand Show quote "Hilary Cotter" wrote: > Your method has 12 logical reads, mine has 2. I suspect mine offers better > performance:) > > -- > Hilary Cotter > Director of Text Mining and Database Strategy > RelevantNOISE.Com - Dedicated to mining blogs for business intelligence. > > This posting is my own and doesn't necessarily represent RelevantNoise's > positions, strategies or opinions. > > Looking for a SQL Server replication book? > http://www.nwsu.com/0974973602.html > > Looking for a FAQ on Indexing Services/SQL FTS > http://www.indexserverfaq.com > > > > "Sha Anand" <ShaAn***@discussions.microsoft.com> wrote in message > news:7A96E73D-65A0-414E-9659-04AE76F5FD4C@microsoft.com... > > small correction... use the following Query > > > > select s1.ProductId,s1.stocklevel,s1.[date], > > (select min(s2.[date]) from stock s2 > > where > > s1.ProductId = s2.ProductId and > > s2.[date] <= s1.[date] and > > s2.stocklevel =0 and s1.stocklevel = 0 and > > s2.[date] >= > > ISNULL((select max(s3.[date]) from stock s3 where s3.[date] < s1.[date] > > and > > s3.stocklevel <> 0 ),s1.[date]) > > ) > > from stock s1 > > order by 1,3 > > > > - Sha Anand > > > > "Sha Anand" wrote: > > > >> You can try this..... > >> > >> select s1.ProductId,s1.stocklevel,s1.date1, > >> (select min(s2.date1) from stock s2 > >> where > >> s1.ProductId = s2.ProductId and > >> s2.date1 <= s1.date1 and > >> s2.stocklevel =0 and s1.stocklevel = 0 and > >> s2.date1 >= > >> (select max(s3.date1) from stock s3 where s3.date1 <= s1.date1 and > >> s3.stocklevel <> 0 ) > >> ) > >> from stock s1 > >> order by 1,3 > >> > >> - Sha Anand > >> > >> "kis***@microlytics.co.uk" wrote: > >> > >> > Hi ML. > >> > > >> > Just modified your original sql by adding the productid constraint in > >> > the where clause of the select statement. SQL below does the trick. > >> > > >> > Thanks again for valuable time and input. > >> > > >> > > >> > select currStock.productid > >> > ,currStock.stocklevel > >> > ,currStock.[date] > >> > ,lastdateoutofstock > >> > = case > >> > when exists( > >> > select * > >> > from stock prevStock > >> > where > >> > (prevStock.stocklevel > >> > = 0) > >> > and > >> > (prevStock.[date] <= currStock.[date]) and (prevstock.productid = > >> > currstock.productid)and > >> > (currstock.stocklevel =0) > >> > ) > >> > then ( > >> > select top 1 prevStock.[date] > >> > from stock prevStock > >> > where > >> > (prevStock.stocklevel > >> > = 0) > >> > and > >> > (prevStock.[date] <= currStock.[date]) > >> > and (prevstock.productid = currstock.productid) > >> > order by > >> > prevStock.[date] Asc > >> > ) > >> > end > >> > from stock currStock > >> > > >> > > >> > > >> > kis***@microlytics.co.uk wrote: > >> > > Hi ML, > >> > > > >> > > I've just tested it on the large table but got back incorrect > >> > > results. > >> > > I then tested the SQL on a sample data (DDL below for your > >> > > information) > >> > > > >> > > It appears that lastdayoutofstock is defaulting on the first date in > >> > > the table rather than getting the true last date out of stock for a > >> > > particuar product. > >> > > > >> > > Thanks for your help by the way. Much appreciated. > >> > > > >> > > ---------------------------------------------------------------------- > >> > > CREATE TABLE [stock] ( > >> > > [productid] [int] NULL , > >> > > [stocklevel] [int] NULL , > >> > > [date] [datetime] NULL > >> > > ) ON [PRIMARY] > >> > > GO > >> > > > >> > > > >> > > insert into stock(productid ,stocklevel ,date ) values > >> > > (1,10,'1/1/2006') > >> > > insert into stock(productid ,stocklevel ,date ) values > >> > > (1,0,'2/1/2006') > >> > > insert into stock(productid ,stocklevel ,date ) values > >> > > (1,0,'3/1/2006') > >> > > insert into stock(productid ,stocklevel ,date ) values > >> > > (1,100,'4/1/2006') > >> > > insert into stock(productid ,stocklevel ,date ) values > >> > > (2,0,'1/1/2006') > >> > > insert into stock(productid ,stocklevel ,date ) values > >> > > (2,0,'2/1/2006') > >> > > insert into stock(productid ,stocklevel ,date ) values > >> > > (2,10,'3/1/2006') > >> > > > >> > > ML wrote: > >> > > > Perhaps a covering index on (date, productid, stocklevel). Just > >> > > > judging from > >> > > > this one query. > >> > > > > >> > > > But - does the query work as it's supposed to? > >> > > > > >> > > > > >> > > > ML > >> > > > > >> > > > --- > >> > > > http://milambda.blogspot.com/ > >> > > >> > > > > Thanks Sha,
The query returns the right results based on the test data. I am now running the query on a large table (around 50 Mill records) and it's taking a while. I have got one index on productid, stock and date. Will wait and see what the execution plan says Sha Anand wrote: Show quote > He wants the following results > > 1 10 2006-01-01 00:00:00.000 NULL > 1 0 2006-02-01 00:00:00.000 2006-02-01 00:00:00.000 > 1 0 2006-03-01 00:00:00.000 2006-02-01 00:00:00.000 > 1 100 2006-04-01 00:00:00.000 NULL > 1 0 2006-05-01 00:00:00.000 2006-05-01 00:00:00.000 > 2 0 2006-01-01 00:00:00.000 2006-01-01 00:00:00.000 > 2 0 2006-02-01 00:00:00.000 2006-01-01 00:00:00.000 > 2 10 2006-03-01 00:00:00.000 NULL > > But your query returns just 2 rows > > 1 2006-02-01 00:00:00.000 2006-05-01 00:00:00.000 > 2 2006-01-01 00:00:00.000 2006-02-01 00:00:00.000 > > - Sha Anand > > "Hilary Cotter" wrote: > > > Your method has 12 logical reads, mine has 2. I suspect mine offers better > > performance:) > > > > -- > > Hilary Cotter > > Director of Text Mining and Database Strategy > > RelevantNOISE.Com - Dedicated to mining blogs for business intelligence. > > > > This posting is my own and doesn't necessarily represent RelevantNoise's > > positions, strategies or opinions. > > > > Looking for a SQL Server replication book? > > http://www.nwsu.com/0974973602.html > > > > Looking for a FAQ on Indexing Services/SQL FTS > > http://www.indexserverfaq.com > > > > > > > > "Sha Anand" <ShaAn***@discussions.microsoft.com> wrote in message > > news:7A96E73D-65A0-414E-9659-04AE76F5FD4C@microsoft.com... > > > small correction... use the following Query > > > > > > select s1.ProductId,s1.stocklevel,s1.[date], > > > (select min(s2.[date]) from stock s2 > > > where > > > s1.ProductId = s2.ProductId and > > > s2.[date] <= s1.[date] and > > > s2.stocklevel =0 and s1.stocklevel = 0 and > > > s2.[date] >= > > > ISNULL((select max(s3.[date]) from stock s3 where s3.[date] < s1.[date] > > > and > > > s3.stocklevel <> 0 ),s1.[date]) > > > ) > > > from stock s1 > > > order by 1,3 > > > > > > - Sha Anand > > > > > > "Sha Anand" wrote: > > > > > >> You can try this..... > > >> > > >> select s1.ProductId,s1.stocklevel,s1.date1, > > >> (select min(s2.date1) from stock s2 > > >> where > > >> s1.ProductId = s2.ProductId and > > >> s2.date1 <= s1.date1 and > > >> s2.stocklevel =0 and s1.stocklevel = 0 and > > >> s2.date1 >= > > >> (select max(s3.date1) from stock s3 where s3.date1 <= s1.date1 and > > >> s3.stocklevel <> 0 ) > > >> ) > > >> from stock s1 > > >> order by 1,3 > > >> > > >> - Sha Anand > > >> > > >> "kis***@microlytics.co.uk" wrote: > > >> > > >> > Hi ML. > > >> > > > >> > Just modified your original sql by adding the productid constraint in > > >> > the where clause of the select statement. SQL below does the trick. > > >> > > > >> > Thanks again for valuable time and input. > > >> > > > >> > > > >> > select currStock.productid > > >> > ,currStock.stocklevel > > >> > ,currStock.[date] > > >> > ,lastdateoutofstock > > >> > = case > > >> > when exists( > > >> > select * > > >> > from stock prevStock > > >> > where > > >> > (prevStock.stocklevel > > >> > = 0) > > >> > and > > >> > (prevStock.[date] <= currStock.[date]) and (prevstock.productid = > > >> > currstock.productid)and > > >> > (currstock.stocklevel =0) > > >> > ) > > >> > then ( > > >> > select top 1 prevStock.[date] > > >> > from stock prevStock > > >> > where > > >> > (prevStock.stocklevel > > >> > = 0) > > >> > and > > >> > (prevStock.[date] <= currStock.[date]) > > >> > and (prevstock.productid = currstock.productid) > > >> > order by > > >> > prevStock.[date] Asc > > >> > ) > > >> > end > > >> > from stock currStock > > >> > > > >> > > > >> > > > >> > kis***@microlytics.co.uk wrote: > > >> > > Hi ML, > > >> > > > > >> > > I've just tested it on the large table but got back incorrect > > >> > > results. > > >> > > I then tested the SQL on a sample data (DDL below for your > > >> > > information) > > >> > > > > >> > > It appears that lastdayoutofstock is defaulting on the first date in > > >> > > the table rather than getting the true last date out of stock for a > > >> > > particuar product. > > >> > > > > >> > > Thanks for your help by the way. Much appreciated. > > >> > > > > >> > > ---------------------------------------------------------------------- > > >> > > CREATE TABLE [stock] ( > > >> > > [productid] [int] NULL , > > >> > > [stocklevel] [int] NULL , > > >> > > [date] [datetime] NULL > > >> > > ) ON [PRIMARY] > > >> > > GO > > >> > > > > >> > > > > >> > > insert into stock(productid ,stocklevel ,date ) values > > >> > > (1,10,'1/1/2006') > > >> > > insert into stock(productid ,stocklevel ,date ) values > > >> > > (1,0,'2/1/2006') > > >> > > insert into stock(productid ,stocklevel ,date ) values > > >> > > (1,0,'3/1/2006') > > >> > > insert into stock(productid ,stocklevel ,date ) values > > >> > > (1,100,'4/1/2006') > > >> > > insert into stock(productid ,stocklevel ,date ) values > > >> > > (2,0,'1/1/2006') > > >> > > insert into stock(productid ,stocklevel ,date ) values > > >> > > (2,0,'2/1/2006') > > >> > > insert into stock(productid ,stocklevel ,date ) values > > >> > > (2,10,'3/1/2006') > > >> > > > > >> > > ML wrote: > > >> > > > Perhaps a covering index on (date, productid, stocklevel). Just > > >> > > > judging from > > >> > > > this one query. > > >> > > > > > >> > > > But - does the query work as it's supposed to? > > >> > > > > > >> > > > > > >> > > > ML > > >> > > > > > >> > > > --- > > >> > > > http://milambda.blogspot.com/ > > >> > > > >> > > > > > > > what about this
select stuff.productid, lastdayoutofstock=min(date), Firstdayoutofstock=max(date) from stuff join (select productid, sl=min(stocklevel) from stuff group by productid) as k on k.productid=stuff.productid and k.sl=stuff.stocklevel where stocklevel=0 group by stuff.productid -- Show quoteHilary Cotter Director of Text Mining and Database Strategy RelevantNOISE.Com - Dedicated to mining blogs for business intelligence. This posting is my own and doesn't necessarily represent RelevantNoise's positions, strategies or opinions. Looking for a SQL Server replication book? http://www.nwsu.com/0974973602.html Looking for a FAQ on Indexing Services/SQL FTS http://www.indexserverfaq.com <kis***@microlytics.co.uk> wrote in message news:1157720744.972933.55720@m79g2000cwm.googlegroups.com... > Hi ML, > > I've just tested it on the large table but got back incorrect results. > I then tested the SQL on a sample data (DDL below for your information) > > It appears that lastdayoutofstock is defaulting on the first date in > the table rather than getting the true last date out of stock for a > particuar product. > > Thanks for your help by the way. Much appreciated. > > ---------------------------------------------------------------------- > CREATE TABLE [stock] ( > [productid] [int] NULL , > [stocklevel] [int] NULL , > [date] [datetime] NULL > ) ON [PRIMARY] > GO > > > insert into stock(productid ,stocklevel ,date ) values > (1,10,'1/1/2006') > insert into stock(productid ,stocklevel ,date ) values > (1,0,'2/1/2006') > insert into stock(productid ,stocklevel ,date ) values > (1,0,'3/1/2006') > insert into stock(productid ,stocklevel ,date ) values > (1,100,'4/1/2006') > insert into stock(productid ,stocklevel ,date ) values > (2,0,'1/1/2006') > insert into stock(productid ,stocklevel ,date ) values > (2,0,'2/1/2006') > insert into stock(productid ,stocklevel ,date ) values > (2,10,'3/1/2006') > > ML wrote: >> Perhaps a covering index on (date, productid, stocklevel). Just judging >> from >> this one query. >> >> But - does the query work as it's supposed to? >> >> >> ML >> >> --- >> http://milambda.blogspot.com/ > try something like this:
create table stuff(productid int,stocklevel int,date datetime) GO insert into stuff(productid ,stocklevel ,date ) values (1,10,'1/1/2006') insert into stuff(productid ,stocklevel ,date ) values (1,0,'2/1/2006') insert into stuff(productid ,stocklevel ,date ) values (1,0,'3/1/2006') insert into stuff(productid ,stocklevel ,date ) values (1,100,'3/1/2006') insert into stuff(productid ,stocklevel ,date ) values (2,0,'1/1/2006') insert into stuff(productid ,stocklevel ,date ) values (2,0,'2/1/2006') insert into stuff(productid ,stocklevel ,date ) values (2,10,'3/1/2006') select stuff.productid, min(date) from stuff join (select productid, sl=min(stocklevel) from stuff group by productid) as k on k.productid=stuff.productid and k.sl=stuff.stocklevel where stocklevel=0 group by stuff.productid -- Show quoteHilary Cotter Director of Text Mining and Database Strategy RelevantNOISE.Com - Dedicated to mining blogs for business intelligence. This posting is my own and doesn't necessarily represent RelevantNoise's positions, strategies or opinions. Looking for a SQL Server replication book? http://www.nwsu.com/0974973602.html Looking for a FAQ on Indexing Services/SQL FTS http://www.indexserverfaq.com <kis***@microlytics.co.uk> wrote in message news:1157712615.660772.281190@b28g2000cwb.googlegroups.com... > Hi, > > I need to get the last date of when stock levels hit zero so I can then > do a datediff to calcualte days out of stock. Here is a table with > sample data > > productid,stocklevel,date > 1,10,1/1/2006 > 1,0,2/1/2006 > 1,0,3/1/2006 > 1,100,3/1/2006 > 2,0,1/1/2006 > 2,0,2/1/2006 > 2,10,3/1/2006 > > Desired result > > productid,stocklevel,date,lastdateoutofstock > 1,10,1/1/2006,null > 1,0,2/1/2006,2/1/2006 > 1,0,3/1/2006 ,2/1/2006 > 1,100,3/1/2006,NULL > 1,0,4/1/2006,4/1/2006 > 2,0,1/1/2006 ,1/1/2006 > 2,0,2/1/2006 ,1/1/2006 > 2,10,3/1/2006,NULL > > Currently I use a cursor to do this but it is taking too long. Hoping > it can be done using Set based T-SQL. > > Thanks > Maybe this example can help your situation.
-- START TSQL CODE set nocount on declare @CourseCompletions table ( EmpID int , CourseID int , CompletionDate datetime , Credits decimal(10,2) ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (101 , 1 , '1/1/2004' , 11.1 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (101 , 2 , '1/1/2004' , 22.2 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (101 , 1 , '1/1/2005' , 11.1 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (101 , 2 , '1/1/2005' , 22.2 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (101 , 1 , '1/1/2006' , 1.11 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (101 , 2 , '1/1/2006' , 2.22 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (102 , 1 , '3/1/2004' , 33.3 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (102 , 2 , '3/1/2004' , 44.4 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (102 , 1 , '3/1/2005' , 33.3 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (102 , 2 , '3/1/2005' , 44.4 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (102 , 1 , '3/1/2006' , 3.33 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (102 , 2 , '3/1/2006' , 4.44 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (103 , 1 , '6/1/2003' , 5.55 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (103 , 2 , '6/1/2003' , 7.77 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (103 , 1 , '6/1/2004' , 55.5 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (103 , 2 , '6/1/2004' , 77.7 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (103 , 1 , '6/1/2005' , 55.5 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (103 , 2 , '6/1/2005' , 77.7 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (103 , 1 , '6/1/2006' , 5.55 ) insert into @CourseCompletions (EmpID , CourseID , CompletionDate , redits ) values (103 , 2 , '6/1/2006' , 7.77 ) --select * from @CourseCompletions SELECT MAX(CompletionDate) FROM @CourseCompletions WHERE EmpID = 101 and CourseID = 1 --This returns '2006-01-01', which is obviously the latest date for this Emp. Can I use the same technique to find the Credits? SELECT MAX(Credits) FROM @CourseCompletions WHERE EmpID = 101 and CourseID = 1 --This returns 11.10, which was the Credits in '1/1/2004', but NOT the Credits for the Max(CompletionDate).... we can clearly see that a new, lower Credits went into effect on 6/1/2006. We didn't get the correct Credits by using MAX. How can we find the Credits that corresponds to that MAX date? We have to join to a subquery, as follows: SELECT CreditsList.EmpID , CreditsList.CourseID, CreditsList.CompletionDate as MostRecentCompletionDate, CreditsList.Credits FROM @CourseCompletions AS CreditsList INNER JOIN ( SELECT top 3 EmpID , CourseID, MAX(CompletionDate) AS LastDate FROM @CourseCompletions GROUP BY EmpID , CourseID ) AS LastDatesAsADerivedTable ON CreditsList.EmpID = LastDatesAsADerivedTable.EmpID AND CreditsList.CourseID = LastDatesAsADerivedTable.CourseID AND CreditsList.CompletionDate = LastDatesAsADerivedTable.LastDate --WHERE CreditsList.EmpID = 101 ORDER BY CreditsList.EmpID , CreditsList.CourseID <kis***@microlytics.co.uk> wrote in message Show quote news:1157712615.660772.281190@b28g2000cwb.googlegroups.com... > Hi, > > I need to get the last date of when stock levels hit zero so I can then > do a datediff to calcualte days out of stock. Here is a table with > sample data > > productid,stocklevel,date > 1,10,1/1/2006 > 1,0,2/1/2006 > 1,0,3/1/2006 > 1,100,3/1/2006 > 2,0,1/1/2006 > 2,0,2/1/2006 > 2,10,3/1/2006 > > Desired result > > productid,stocklevel,date,lastdateoutofstock > 1,10,1/1/2006,null > 1,0,2/1/2006,2/1/2006 > 1,0,3/1/2006 ,2/1/2006 > 1,100,3/1/2006,NULL > 1,0,4/1/2006,4/1/2006 > 2,0,1/1/2006 ,1/1/2006 > 2,0,2/1/2006 ,1/1/2006 > 2,10,3/1/2006,NULL > > Currently I use a cursor to do this but it is taking too long. Hoping > it can be done using Set based T-SQL. > > Thanks > |
|||||||||||||||||||||||