2016-11-29 70 views
1

我不是一个SQL的家伙,我用它在过去,很少有一个问题,不能由谷歌解决...但是这次我需要问社区。每个产品返回一个SQL行与价格和最新日期

我有一个名为“交易”有数据这样的表的数据库:

ProdNo | Price | TransactionDate | PurchasedBy | etc..... 
---------------------------------------------------------- 
3STRFLEX | 13.02 | 20162911  | AWC   | ..... 
3STRFLEX | 15.02 | 20162011  | DWC   | ..... 
3STRFLEX | 15.02 | 20160101  | AWC   | ..... 
AFTV2  | 35.49 | 20162708  | AWC   | ..... 
AFTV2  | 29.99 | 20160106  | DWC   | ..... 
AFTV2  | 29.99 | 20160205  | AWC   | ..... 

所需的输出是:

ProdNo | Price | TransactionDate 
----------------------------------- 
3STRFLEX | 13.02 | 20162911   
AFTV2  | 35.49 | 20162708   

我已经尝试了写这个我自己和我结束与SQL是这样的:

select t.ProdNo, t.TransactionDate as 'LastPurchaseDate', t.Price 
from Transactions t 
inner join (
    select ProdNo, max(TransactionDate) as 'LastPurchaseDate' 
    from Transactions 
    WHERE Price > 0 
    group by ProdNo 
) tm on t.ProdNo = tm.ProdNo and LastPurchaseDate = tm.LastPurchaseDate 

但是在我的数据集中这返回(减少),其中显示多每个产品

ProdNo | LastPurchaseDate | Price 
3STRFLX | 20120924   | 0.000000 
3STRFLX | 20120924   | 22.000000 
3STRFLX | 20150623   | 0.000000 
3STRFLX | 20150623   | 1.220000 
3STRFLX | 20150623   | 1.222197 

行,以便确认:我想每个产品1行中,无论价格是购买最新的日期,但我需要在返回的数据中的价格。

感谢

+0

这个问题接受了下来投票。但没有评论,OP没有办法解决/解决这个问题。这也使得很难辩论这一点。我看不出有什么问题。但是,也许我会同意一个评论......按照我的观点,我已经提出了包括样本数据,预期产出,原始努力和对问题的明确描述。 –

+0

@ destination-data谢谢。我也没有看到这个问题,也许我错过了一些规则或东西 –

回答

6

您可以使用CTE和分级功能PARTITION BY

WITH CTE AS 
(
    select t.ProdNo, t.TransactionDate as 'LastPurchaseDate', t.Price, 
      rn = row_number() over (partition by ProdNo order by TransactionDate desc) 
    from Transactions t 
) 
SELECT ProdNo, LastPurchaseDate, Price FROM CTE WHERE RN = 1 
+0

这似乎工作完美。谢谢!我现在将研究CTE,所以希望我不需要再次提问 –

+0

如果每条'ProdNo'具有相同的'max(TransactionDate)' – HoneyBadger

1

你在正确的轨道上。如果您使用:

select t.ProdNo, t.TransactionDate as 'LastPurchaseDate', t.Price 
from Transactions t 
inner join (
    select ProdNo, max(TransactionDate) as 'LastPurchaseDate' 
    from Transactions 
    WHERE Price > 0 
    group by ProdNo 
) tm on t.ProdNo = tm.ProdNo and t.TransactionDate= tm.LastPurchaseDate 

请注意连接条件的更改。

查询中发生了什么:LastPurchaseDate = tm.LastPurchaseDate。只有一列叫做LastPurchaseDate,所以它将它与自己等同起来,这总是正确的。所以你只剩下t.ProdNo = tm.ProdNo,因为t.ProdNo不是唯一的,你会为每个t.ProdNo返回多个记录。

+0

,那么这将返回任意记录。不幸的是,这仍然返回多行。感谢您发现,但。 –

+0

@TedJames,啊,我知道,你有更多的一个记录具有相同的'max(TransactionDate)'。您必须决定要选择哪些记录。 'ROW_NUMBER()'可以提供帮助,但它会返回任意记录。 – HoneyBadger

0

试试这个。通过使用row_number()。

   select * from 
      (
      select 
      T.ProdNo, 
      T.TransactionDate as 'LastPurchaseDate', 
      T.Price,   
      row_number() over (partition by ProdNo order by TransactionDate desc) as rnk 
      from Transactions T 
      )a 
      where rnk='1' 
+1

为什么'rnk ='1''? 'ROW_NUMBER()'返回一个'bigint',所以'rnk = 1'更有意义。 – HoneyBadger

+0

@HoneyBadger你也是对的。 –

-1
SELECT A.ProdNo ,Price ,A.TransactionDate,PurchasedBy 
FROM #Transactions 
JOIN 
(
SELECT ProdNo,MAX(TransactionDate) TransactionDate 
FROM #Transactions 
GROUP BY ProdNo 
)A ON A.TransactionDate = #Trans.TransactionDate 
1

一种方法是使用ROW_NUMBER windowed function

我的查询使用common table expression (CTE)来提供样本数据。使用这种技术时,你总是需要一个CTE,或者subquery。这是因为在SELECT子句中生成的值不能用于WHERE子句。这是一个叫做Logical Processing Order的结果。换一种说法; SQL Server在过滤数据后生成行号。 CTEs /子查询为您提供了第二个WHERE子句,即在生成行号后执行操作**。

-- Returning the most recent record from a transaction table. 
WITH SampleDate AS 
    (
     SELECT 
      ROW_NUMBER() OVER (PARTITION BY ProdNo ORDER BY TransactionDate DESC) AS Rn, 
      * 
     FROM 
      (
       VALUES      
        ('3STRFLEX', 13.02, '20162911', 'AWC '), 
        ('3STRFLEX', 15.02, '20162011', 'DWC '), 
        ('3STRFLEX', 15.02, '20160101', 'AWC '), 
        ('AFTV2' , 35.49, '20162708', 'AWC '), 
        ('AFTV2' , 29.99, '20160106', 'DWC '), 
        ('AFTV2' , 29.99, '20160205', 'AWC ') 
      ) AS x(ProdNo, Price, TransactionDate, PurchasedBy) 
    ) 
SELECT 
    * 
FROM 
    SampleDate 
WHERE 
    Rn = 1 
; 

**其实这不完全正确。它被称为逻辑订单的原因。 SQL Sever可以/将会以您认为合适的方式执行您的查询。但是,无论您的查询是在物理上执行的,它都会遵守逻辑顺序。

0

请试试这个 - - 如果一个ProdNo有两个相同的最高TransactionDate,将返回两两行

select ProdNo,Price,TransactionDate from Transactions t 
where not exists (select 1 from Transactions where ProdNo=t.ProdNo and TransactionDate>t.TransactionDate) 
相关问题