我有这个查询创建了同一个表的两个副本(原始表没有唯一的ID)所以我使用row_number
来排序表:
SELECT ROW_NUMBER() OVER(ORDER BY Policy ASC) AS RowNumber, *
INTO Example1
FROM Payments
SELECT ROW_NUMBER() OVER(ORDER BY Policy ASC) AS RowNumber, *
INTO Example2
FROM Payments
我想检查“导入”中的值是否与我在按政策排序的表格中的实际行之前的“导入”中的值相同。
我使用行号对我的两个表进行了比较以检查实际值之前的值,如果它们都等于它,则将“Review”列设置为选中,这意味着导入它与从行中导入的相同在实际价值之前。
这就是我的所作所为,但执行需要一段时间......所以我想知道我是否可以优化此查询或以其他方式做我想要的事情?
DECLARE @intCount INT
SELECT @intCount = COUNT(DISTINCT(RowNumber)) FROM Example1
DECLARE @i int
SET @i = 1
WHILE @i <= @intCount
BEGIN
DECLARE @Import decimal(15,2)
SELECT @Import = Import
FROM Example1
WHERE RowNumber = @i
DECLARE @RowNumberBefore bigint
SELECT @RowNumberBefore = RowNumber
FROM Example1
WHERE RowNumber = @i - 1
UPDATE TOP (1) Example1
SET Review = 'Checked'
FROM Example1 a
JOIN Example2 b ON a.Policy = b.Policy
WHERE a.Import = @Import
AND a.RowNumber = @RowNumberBefore
SET @i = @i + 1
END
期望结果的示例:
如果我有这个:
RowNumber Policy Import Review
--------- ------ ------ ------
1 0001 586.45
2 0002 586.45
3 0003 65.50
4 0004 249.30
5 0005 65.50
6 0005 153.35
7 0006 32.50
8 0006 32.50
9 0007 32.50
10 0009 250.00
我想用'checked'更新评论,如果导入它与实际导入之前的导入相同(我不能将策略用作id,因为它可能有重复的值)。
所以,如果我有按政策排序的值(使用rowcount),我正在使用rowNumber
按照我想要的顺序比较'政策':
RowNumber Policy Import Review
--------- ------ ------ ------
1 0001 586.45 Checked
2 0002 586.45 Checked
3 0003 65.50
4 0004 249.30
5 0005 65.50
6 0005 153.35
7 0006 32.50 Checked
8 0006 32.50 Checked
9 0007 32.50 Checked
10 0009 250.00
答案 0 :(得分:3)
您可以使用LAG()
在一个查询中执行此操作以获取上一行值,如下所示:
SELECT *, CASE WHEN Import = LAG(Import) over (ORDER BY Policy)
THEN 'Checked'
ELSE 'Whatever'
END Review
INTO Example1
FROM Payments
SQL Server 2008和之前将使用类似于您的方法的逻辑,但是在表级而不是行级执行。这是一种方式:
SELECT p.*, CASE WHEN p.Import = p2.Import
THEN 'Checked'
ELSE 'Whatever'
END as Review
INTO Example1
FROM (SELECT *, ROW_NUMBER() over (ORDER BY policy) RN
FROM Payment) p
LEFT JOIN (SELECT Import, ROW_NUMBER() over (ORDER BY policy) RN
FROM Payment) p2 on p.RN = p2.RN - 1
答案 1 :(得分:2)
我想检查“导入”中的值是否为&#39;它与&#39;导入&#39;中的值相同从我按照政策订购的表中的实际行之前的行。
我不知道row_number()
或update
与此问题的关系。如果您想确定import
更改的行,那么如何:
select p.*
from (select p.*,
lag(p.import) over (order by p.policy) as prev_import
from payments p
) p
where prev_import <> import;
编辑:
在SQL Server 2008中,您只需使用outer apply
:
select p.*
from (select p.*, p2.import as prev_import
from payments p outer apply
(select top 1 p2.*
from payments p2
where p2.policy < p.policy
order by p2.policy desc
) p2
) p
where prev_import <> import;
性能仍然非常差,但payments(policy, import)
上的索引会有所帮助。
答案 2 :(得分:0)
首先,不需要使用row_number创建两个版本。您可以加入同一张桌子。
SELECT Payment.Policy, Payment.Import, ROW_NUMBER() over (ORDER BY policy) RN
INTO #temp
FROM Payment
如果您的表很大,您现在可以为其添加索引。注意我只使用了我需要的列。然后查询是
SELECT t.Import,t.policy, CASE WHEN t.Import = t2.Import
THEN 'Checked'
ELSE 'Whatever'
END as Review
FROM #Temp t
LEFT JOIN #Temp t2 on t.RN = t2.RN - 1
如果您确实想要更新原始表,那么您还有一个问题,因为表中没有唯一标识符。那你加入什么?此外,我可以看到您的数据存在一些问题,因为您已经订购了策略但是有多个策略记录。假设您有这些数据:
RowNumber Policy Import Review
--------- ------ ------ ------
1 0001 586.45
2 0002 586.45
3 0003 65.50
4 0004 249.30
5 0005 65.50
6 0005 249.30
7 0006 32.50
8 0006 32.50
9 0007 32.50
10 0009 250.00
现在,政策中的审查0004和0005的价值可能取决于它选择处理两个0005记录的方式。一个是匹配,但另一个不会,你没有什么可以保证这些005记录的顺序。整个问题是一个经典案例,说明为什么不应该创建没有主键的表。