我有一个评级系统,任何人都可以评论其他人。每个人可以由一个人不止一次地评判。对于平均值的计算,我想只包括最新的值。
这可以用SQL吗?
结果:
表格可能如下所示:evaluator, evaluatee, rating, date
。
亲切的问候
迈克尔
答案 0 :(得分:5)
这完全有可能。
我们假设您的表结构如下所示:
CREATE TABLE [dbo].[Ratings](
[Evaluator] varchar(10),
[Evaluatee] varchar(10),
[Rating] int,
[Date] datetime
);
和这样的值:
INSERT INTO Ratings
SELECT 'Person 1', 'Person 2', 5, '2011-02-01' UNION
SELECT 'Person 1', 'Person 2', 2, '2011-03-01' UNION
SELECT 'Person 2', 'Person 1', 6, '2011-02-01' UNION
SELECT 'Person 2', 'Person 1', 3, '2011-03-01' UNION
SELECT 'Person 3', 'Person 1', 5, '2011-05-01'
然后人1的平均评分为:
SELECT AVG(Rating) FROM Ratings r1
WHERE Evaluatee='Person 1' and not exists
(SELECT 1 FROM Ratings r2
WHERE r1.Evaluatee = r2.Evaluatee AND
r1.evaluator=r2.evaluator AND
r1.date < r2.date)
结果:
4
或者对于所有评估者,按评估者分组:
SELECT Evaluatee, AVG(Rating) FROM Ratings r1
WHERE not exists
(SELECT 1 FROM Ratings r2
WHERE r1.Evaluatee = r2.Evaluatee AND
r1.evaluator = r2.evaluator AND
r1.date < r2.date)
GROUP BY Evaluatee
结果:
Person 1 4
Person 2 2
这可能看起来像隐含的假设,即没有相同日期的条目; 但这实际上不是问题:如果这样的条目可以存在,那么你无法决定以后哪些是后来的;你只能在它们之间随机选择。如此处所示,它们都被包含在内并被平均 - 这可能是你可以获得的最佳解决方案(虽然它略微偏爱那个人,给他两票)。
要完全避免这个问题,您可以简单地将Date作为主键的一部分或唯一索引 - 这里显而易见的主键选择是列(Evaluator,Evaluatee,Date)。
答案 1 :(得分:1)
declare @T table
(
evaluator int,
evaluatee int,
rating int,
ratedate date
)
insert into @T values
(1, 2, 5, '20110102'),
(1, 2, 2, '20110103'),
(2, 1, 6, '20110102'),
(2, 1, 3, '20110103'),
(3, 1, 5, '20110105')
select evaluatee,
avg(rating) as avgrating
from (
select evaluatee,
rating,
row_number() over(partition by evaluatee, evaluator
order by ratedate desc) as rn
from @T
) as T
where T.rn = 1
group by evaluatee
结果:
evaluatee avgrating
----------- -----------
1 4
2 2
答案 2 :(得分:0)
这是可能的,但它可能真的很难 - SQL不是为了比较行,而是为了比较列。我强烈建议您保留一个仅包含最新数据的附加表,并将其余表存储在存档表中。
如果必须这样做,那么我需要一个完整的表结构来尝试为此编写查询。特别是我需要知道哪些是独特的索引。