| Author |
Topic |
|
dang12
Starting Member
12 Posts |
Posted - 2008-04-24 : 06:26:14
|
| Hi,I have a SQL2005 db for tracking the prices of products at multiple retailers. The basic structure is, 'products' table lists individual products, 'retailer_products' table lists current prices of the products at multiple retailers, and 'price_history' table records when the price of a product changes at any retailer. The prices are checked from each retailer daily, but a row is added to the 'price_history' only when the price at the retailer changes.Database create script:[url]http://www.boltfile.com/directdownload/db_create_script.sql[/url]Full database backup:[url]http://www.boltfile.com/directdownload/database.bak[/url]Database diagram:[url]http://www.boltfile.com/directdownload/diagram_0.pdf[/url]I have the following query to retrieve the price history of a given product at multiple retailers:SELECT price_history.datetimeofchange, retailer.name, price_history.priceFROM product, retailer, retailer_product, price_historyWHERE product.id = 'b486ed47-4de4-417d-b77b-89819bc728cd'AND retailer_product.retailerid = retailer.idAND retailer_product.associatedproductid = product.idAND price_history.retailer_productid = retailer_product.idThis gives the following results:2008-03-08 Example Retailer 2 2.32008-03-28 Example Retailer 1 1.82008-03-30 Example Retailer 2 2.12008-04-01 Example Retailer 1 1.432008-04-03 Example Retailer 1 1.4The question(s) I have are how can I:1 - Get the price of a product at a given retailer at a given date/timeFor example, get the price of the product at Retailer 2 on 03/28/2008. Table only contains data for Retailer 1 for this date, the behaviour I want is when there is no data available for the query to find the last data at which there was data from that retailer, and use the price from that point - i.e. so for this example the query should result in 2.3 as the price, given that was the last recorded price change from that retailer (03/08/2008).2 - Get the average price of a product at a given retailer at a given date/timeIn this case we would need to perform (1) across all retailers, then average the resultsI'd really appretiate anyone's help on this :)many thanks in advance,dg |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2008-04-24 : 07:13:47
|
1.SELECT @Date, r.name, ph.priceFROM retailer rINNER JOIN retailer_product rpON rp.[retailerid]=r.idINNER JOIN price_history phON ph.[retailer_productid]=rp.idINNER JOIN (SELECT retailer_productid,MAX(datetimeofchange) as maxdateFROM price_history WHERE datetimeofchange<=@Date)tempON ph.retailer_productid=temp.retailer_productidAND ph.datetimeofchange=temp.maxdateWHERE r.name = @Retailer 2.SELECT p.name, AVG(ph.price)FROM retailer rINNER JOIN retailer_product rpON rp.[retailerid]=r.idINNER JOIN product pON p.id=rp.[associatedproductid]INNER JOIN price_history phON ph.[retailer_productid]=rp.idINNER JOIN (SELECT retailer_productid,MAX(datetimeofchange) as maxdateFROM price_history WHERE datetimeofchange<=@Date)tempON ph.retailer_productid=temp.retailer_productidAND ph.datetimeofchange=temp.maxdateGROUP BY p.name |
 |
|
|
dang12
Starting Member
12 Posts |
Posted - 2008-04-24 : 07:39:17
|
| Hi visakh16,thanks very much for your help - really appretiated! :)When I am running the following query I'm getting:Msg 8120, Level 16, State 1, Line 9Column 'price_history.retailer_productid' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.DECLARE @Date datetimeSELECT @Date = '28/03/2008'DECLARE @Retailer nvarchar(250)SELECT @Retailer = 'Example Retailer 2'SELECT @Date, r.name, ph.priceFROM retailer rINNER JOIN retailer_product rpON rp.[retailerid]=r.idINNER JOIN price_history phON ph.[retailer_productid]=rp.idINNER JOIN (SELECT retailer_productid,MAX(datetimeofchange) as maxdateFROM price_history WHERE datetimeofchange<=@Date)tempON ph.retailer_productid=temp.retailer_productidAND ph.datetimeofchange=temp.maxdateWHERE r.name = @RetailerIs there something else I'm missing?thanks again for your help :)dg |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2008-04-24 : 07:45:37
|
Sorry missed a bit while postingSELECT @Date, r.name, ph.priceFROM retailer rINNER JOIN retailer_product rpON rp.[retailerid]=r.idINNER JOIN price_history phON ph.[retailer_productid]=rp.idINNER JOIN (SELECT retailer_productid,MAX(datetimeofchange) as maxdateFROM price_history WHERE datetimeofchange<=@DateGROUP BY retailer_productid)tempON ph.retailer_productid=temp.retailer_productidAND ph.datetimeofchange=temp.maxdateWHERE r.name = @Retailer |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2008-04-24 : 08:21:50
|
| What was the value passed for @Date? Also it would be worthwhile if you set the date format to your passed on format using SET DATEFORMATie if you are passing date value in ddmmyyyy format useSET DATEFORMAT dmy on top of the query batch |
 |
|
|
dang12
Starting Member
12 Posts |
Posted - 2008-04-24 : 09:30:57
|
| Thanks again for your help the first query is working correctly now! :)I'm now running the 2nd (to get the average price across all retailers at a given date/time:DECLARE @Date datetimeSELECT @Date = '03/30/2008'DECLARE @ProductId uniqueidentifierSELECT @ProductId = 'b486ed47-4de4-417d-b77b-89819bc728cd'SELECT @Date AS 'DateTime', p.name as 'Product', AVG(ph.price) AS 'AveragePrice'FROM retailer rINNER JOIN retailer_product rpON rp.[retailerid]=r.idINNER JOIN product pON p.[id] = rp.associatedproductidINNER JOIN price_history phON ph.[retailer_productid]=rp.idINNER JOIN (SELECT retailer_productid,MAX(datetimeofchange) as maxdateFROM price_history WHERE datetimeofchange<=@DateGROUP BY retailer_productid)tempON ph.retailer_productid=temp.retailer_productidAND ph.datetimeofchange=temp.maxdateWHEREp.Id = @ProductIdGROUP BY p.nameThis gives the following result:2008-03-30 00:00:00.000 Bread 500 grams 1.95from the data:2008-03-08 00:00:00.000 Example Retailer 2 2.32008-03-28 00:00:00.000 Example Retailer 1 1.82008-03-30 00:00:00.000 Example Retailer 2 2.12008-04-01 00:00:00.000 Example Retailer 1 1.432008-04-03 00:00:00.000 Example Retailer 1 1.4However as the date passed in in @Date is 03/30/2008 I would expect the average to be (2.3 + 1.8 + 2.1) / 3 = 2.06 - not sure where the 1.95 is coming from...many thanks in advance,dg |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2008-04-24 : 11:14:52
|
quote: Originally posted by dang12 Thanks again for your help the first query is working correctly now! :)I'm now running the 2nd (to get the average price across all retailers at a given date/time:DECLARE @Date datetimeSELECT @Date = '03/30/2008'DECLARE @ProductId uniqueidentifierSELECT @ProductId = 'b486ed47-4de4-417d-b77b-89819bc728cd'SELECT @Date AS 'DateTime', p.name as 'Product', AVG(ph.price) AS 'AveragePrice'FROM retailer rINNER JOIN retailer_product rpON rp.[retailerid]=r.idINNER JOIN product pON p.[id] = rp.associatedproductidINNER JOIN price_history phON ph.[retailer_productid]=rp.idINNER JOIN (SELECT retailer_productid,MAX(datetimeofchange) as maxdateFROM price_history WHERE datetimeofchange<=@DateGROUP BY retailer_productid)tempON ph.retailer_productid=temp.retailer_productidAND ph.datetimeofchange=temp.maxdateWHEREp.Id = @ProductIdGROUP BY p.nameThis gives the following result:2008-03-30 00:00:00.000 Bread 500 grams 1.95from the data:2008-03-08 00:00:00.000 Example Retailer 2 2.32008-03-28 00:00:00.000 Example Retailer 1 1.82008-03-30 00:00:00.000 Example Retailer 2 2.12008-04-01 00:00:00.000 Example Retailer 1 1.432008-04-03 00:00:00.000 Example Retailer 1 1.4However as the date passed in in @Date is 03/30/2008 I would expect the average to be (2.3 + 1.8 + 2.1) / 3 = 2.06 - not sure where the 1.95 is coming from...many thanks in advance,dg
I think i got you this time. So you want average of all prices before entered date even if we have more than price record for a retailer. can you change like this and try:-SELECT p.name, AVG(ph.price)FROM retailer rINNER JOIN retailer_product rpON rp.[retailerid]=r.idINNER JOIN product pON p.id=rp.[associatedproductid]INNER JOIN price_history phON ph.[retailer_productid]=rp.idWHERE ph.datetimeofchange<=@DateGROUP BY p.name |
 |
|
|
dang12
Starting Member
12 Posts |
Posted - 2008-04-24 : 11:34:11
|
| Not quite :)The statement needed is:"Get the average price across all retailers for the given product, at the given date/time"really appretiate all your help! :)dg |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2008-04-24 : 11:38:34
|
quote: Originally posted by dang12 Not quite :)The statement needed is:"Get the average price across all retailers for the given product, at the given date/time"really appretiate all your help! :)dg
given date? thats meaans exactly on that date? or all that heppen on or before? |
 |
|
|
dang12
Starting Member
12 Posts |
Posted - 2008-04-24 : 14:13:55
|
| given date = exactly on that date :)thanks again,dg |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2008-04-24 : 15:00:39
|
| SELECT p.name, AVG(ph.price)FROM retailer rINNER JOIN retailer_product rpON rp.[retailerid]=r.idINNER JOIN product pON p.id=rp.[associatedproductid]INNER JOIN price_history phON ph.[retailer_productid]=rp.idWHERE ph.datetimeofchange=@DateGROUP BY p.name |
 |
|
|
dang12
Starting Member
12 Posts |
Posted - 2008-04-25 : 04:47:49
|
| Hi,I think what I need is basically the average of the price column returned by the following query:DECLARE @Date datetimeSELECT @Date = '04/28/2008'DECLARE @Retailer nvarchar(250)SELECT @Retailer = 'Example Retailer 2'DECLARE @ProductId uniqueidentifierSELECT @ProductId = 'b486ed47-4de4-417d-b77b-89819bc728cd'SELECT @Date, r.name, ph.price, p.nameFROM retailer rINNER JOIN retailer_product rpON rp.[retailerid]=r.idINNER JOIN product pON p.[id] = rp.associatedproductidINNER JOIN price_history phON ph.[retailer_productid]=rp.idINNER JOIN (SELECT retailer_productid,MAX(datetimeofchange) as maxdateFROM price_history WHERE datetimeofchange<=@DateGROUP BY retailer_productid)tempON ph.retailer_productid=temp.retailer_productidAND ph.datetimeofchange=temp.maxdateWHEREp.Id = @ProductIdgives results:2008-04-28 00:00:00.000 Example Retailer 2 2.1 Bread 500 grams2008-04-28 00:00:00.000 Example Retailer 1 1.4 Bread 500 gramsand I need the average of all the prices returned - i.e. (2.1 + 1.4) / 2 = 1.75Could you show me how to write a query that reads the above query into a temp table then performs an AVG on the price column, the result I'd hope to get would be:2008-04-28 00:00:00.000 Bread 500 grams 1.75many thanksdg |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2008-04-25 : 07:10:49
|
| SELECT @Date, p.name, avg(ph.price)FROM retailer rINNER JOIN retailer_product rpON rp.[retailerid]=r.idINNER JOIN product pON p.[id] = rp.associatedproductidINNER JOIN price_history phON ph.[retailer_productid]=rp.idINNER JOIN (SELECT retailer_productid,MAX(datetimeofchange) as maxdateFROM price_history WHERE datetimeofchange<=@DateGROUP BY retailer_productid)tempON ph.retailer_productid=temp.retailer_productidAND ph.datetimeofchange=temp.maxdateWHEREp.Id = @ProductIdGROUP BY @Date,p.name |
 |
|
|
dang12
Starting Member
12 Posts |
Posted - 2008-04-25 : 07:14:51
|
| Thanks for your reply - that query gives:Msg 164, Level 15, State 1, Line 44Each GROUP BY expression must contain at least one column that is not an outer reference.many thanksdg |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2008-04-25 : 07:33:38
|
| SELECT ph.datetimeofchange, p.name, avg(ph.price)FROM retailer rINNER JOIN retailer_product rpON rp.[retailerid]=r.idINNER JOIN product pON p.[id] = rp.associatedproductidINNER JOIN price_history phON ph.[retailer_productid]=rp.idINNER JOIN (SELECT retailer_productid,MAX(datetimeofchange) as maxdateFROM price_history WHERE datetimeofchange<=@DateGROUP BY retailer_productid)tempON ph.retailer_productid=temp.retailer_productidAND ph.datetimeofchange=temp.maxdateWHEREp.Id = @ProductIdGROUP BY ph.datetimeofchange,p.name |
 |
|
|
dang12
Starting Member
12 Posts |
Posted - 2008-04-25 : 07:43:26
|
| I've slightly modified your query to show the retailer:SELECT ph.datetimeofchange, p.name, avg(ph.price), r.nameFROM retailer rINNER JOIN retailer_product rpON rp.[retailerid]=r.idINNER JOIN product pON p.[id] = rp.associatedproductidINNER JOIN price_history phON ph.[retailer_productid]=rp.idINNER JOIN (SELECT retailer_productid,MAX(datetimeofchange) as maxdateFROM price_history WHERE datetimeofchange<=@DateGROUP BY retailer_productid)tempON ph.retailer_productid=temp.retailer_productidAND ph.datetimeofchange=temp.maxdateWHEREp.Id = @ProductIdGROUP BY ph.datetimeofchange,p.name, r.namewhich gives:2008-03-08 00:00:00.000 Bread 500 grams 2.3 Example Retailer 22008-03-28 00:00:00.000 Bread 500 grams 1.8 Example Retailer 1However when I'm after is one query that takes those results and gives the average price across all retailers for the product specified in @ProductId for the date specified in @Date.So if SELECT @Date = '03/28/2008' I would expect the query to result in 1 row showing:2008-03-28 00:00:00.000 Bread 500 grams 2.05Where 2.05 is calculated from (2.3 + 1.8) / 2 = 2.05Essentially - how can I get the query to return 1 row that shows the average price across the results from the previous query?many thanksdg |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2008-04-25 : 08:01:34
|
| [code]SELECT r.name,t.name,t.datetimeofchange,t.avgpriceFROM retailer rINNER JOIN retailer_product rpON rp.[retailerid]=r.idINNER JOIN (SELECT p.id,ph.datetimeofchange, p.name, avg(ph.price) as avgpriceFROM product pINNER JOIN price_history phON ph.[retailer_productid]=rp.idINNER JOIN (SELECT retailer_productid,MAX(datetimeofchange) as maxdateFROM price_history WHERE datetimeofchange<=@DateGROUP BY retailer_productid)tempON ph.retailer_productid=temp.retailer_productidAND ph.datetimeofchange=temp.maxdateGROUP BY ph.datetimeofchange,p.name,p.id)tON t.[id] = rp.associatedproductidWHEREp.Id = @ProductId[/code] |
 |
|
|
dang12
Starting Member
12 Posts |
Posted - 2008-04-25 : 08:40:56
|
| gives:Msg 4104, Level 16, State 1, Line 46The multi-part identifier "rp.id" could not be bound.Msg 4104, Level 16, State 1, Line 46The multi-part identifier "p.Id" could not be bound.thanks again for your assistance :)dg |
 |
|
|
|