2009-09-30 64 views
3

此查詢的目的是爲銷售的產品帶回產品及其價格,價格應該從最接近的日期開始,但不等於過去的日期,基本上是最近的可用價格。沒有每天的價格記錄。在where子句中使用匯總select語句有些問題。有一個更好的方法嗎?也許在加入標準?使用where條款中的select()函數改進Sql查詢

 select 
     p.ProductName, 
     pp.Price, 
     pp.Date, 
     from product p 
     inner join productprice pp on p.productid = pp.productid 
     where 
     pp.evaluationdate = (select max(Date) from productprice 
          where productid = p.productid 
          and date < @DateIn) 
     and p.producttype = 'OnSale' 

實際上查詢有點複雜,但實質上是這個問題。感謝您的輸入。

編輯 將有一個以上的產品返回

編輯 我既@Remus Rusanu的和@公里的試驗的建議(雖然@Remus Rusanu脫下)所有三個,包括我原創,在性能方面似乎差不多。我試圖決定是否以某種其他無形方式提供了對其他方面的好處,即維護,自我記錄等,因爲這將由其他人維護。再次感謝。

回答

5

試試這個:

我覺得跟CTE上面的查詢將具有相同的查詢計劃,作爲該derived table version from @Remus Rusanu

:基於OP的評論

;WITH CurrentPrice AS 
(
SELECT productid,max(Date) AS Date 
    FROM productprice 
    WHERE date < @DateIn 
    GROUP BY productid 
) 

select 
    p.ProductName, 
    pp.Price, 
    pp.Date, 
    from product p 
     inner join CurrentPrice pa on p.productid = pa.productid 
     inner join productprice pp on pa.productid = pp.productid AND pa.Date=pp.Date 
    where p.producttype = 'OnSale' 

編輯但是,如果productprice表很大,則可能需要通過「OnSale「like like:

;WITH CurrentPrice AS 
(
select 
    p.productid, 
    MAX(pp.Date) AS Date 
    from product p 
     inner join productprice pp on pa.productid = pp.productid 
    where p.producttype = 'OnSale' AND pp.date < @DateIn 
    GROUP BY productid 
) 
select 
    p.ProductName, 
    pp.Price, 
    pp.Date, 
    from CurrentPrice   pa 
     inner join product  p on pa.productid = p.productid 
     inner join productprice pp on pa.productid = pp.productid AND pa.Date=pp.Date 
    where p.producttype = 'OnSale' 
+0

我認爲這可能會起作用,儘管我會限制CTE根據「onsale」標準過濾產品,但它看起來基本上是一樣的。對於子查詢,性能與CTE會有什麼不同? ProductPrice是一張大桌 – Gratzy 2009-09-30 19:19:29

+0

我的回覆與你的回覆基本相同,所以我將其刪除。 – 2009-09-30 20:12:16

0
SELECT TOP 1 p.ProductName, pp.Price, pp.Date, 
FROM product p 
INNER JOIN productprice pp on ... 
WHERE pp.date < @DateIn 
ORDER BY pp.date DESC 
+0

對不起將會有一個以上的產品退回,銷售的所有產品,所以前1只會帶來我是第一個產品的第一個記錄 – Gratzy 2009-09-30 19:07:22

1

這是窗口函數的工作嗎?

SELECT * FROM (select 
      p.ProductName, 
      pp.Price, 
      pp.Date, 
      RANK() OVER(PARTITION BY p.ProductId ORDER BY pp.Date DESC) as row_rank 
      from product p 
       join productprice pp on p.productid = pp.productid 
      where 
       pp.date < @DateIn 
       and p.producttype = 'OnSale' 
    ) saleprice 
    where row_rank = 1 

編輯分區的ID(假設你的主鍵是最快的),在價格上partiton刪除

+0

我想到了這樣的解決方案,但與CTE一起。我認爲RANK()應該是:_RANK()OVER(PARTITION BY p.Productid ORDER BY p.Productid,pp.Date DESC)as row_rank_ – 2009-09-30 20:14:02

+0

你說得對,我做了RANK(),它只需要分區產品ID,但順序不需要它,我想。編輯 – Damon 2009-09-30 20:20:16