我不是一个SQL人,我过去曾经使用它,很少有一个问题无法通过谷歌解决......但这次我需要问社区。 p>
我有一个名为'Transactions'的数据库,它有这样的数据:
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
所以要确认一下:无论价格如何,我希望每个产品购买一行,不管价格如何,但我需要退回数据中的价格。
由于
答案 0 :(得分: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
答案 1 :(得分: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
返回多条记录。
答案 2 :(得分:1)
一种方法使用ROW_NUMBER windowed function。
我的查询使用common table expression (CTE)来提供示例数据。使用此技术时,您始终需要CTE或subquery。这是因为SELECT子句中生成的值不可用于WHERE子句。这是Logical Processing Order之类的结果。换一种说法; SQL Server在过滤数据后生成行号。 CTE /子查询为您提供了第二个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可以/将以任何它认为合适的方式执行您的查询。但是,无论您的查询是物理执行的,它都会遵循逻辑顺序。
答案 3 :(得分: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'
答案 4 :(得分: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)
答案 5 :(得分:-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