我遇到了一些SQL,其中我有几行数据,我想从上一行中减去一行并让它一直重复。
所以这是表格:
CREATE TABLE foo ( id, length )
INSERT INTO foo (id,length) VALUES(1,1090) INSERT INTO foo (id,length) VALUES(2,888) INSERT INTO foo (id,length) VALUES(3,545) INSERT INTO foo (id,length) VALUES(4,434) INSERT INTO foo (id,length) VALUES(5,45)
我希望结果显示一个名为差异的第三列,即从下面一行中减去一行,最后一行从零减去。
+------+------------------------+ | id |length | difference | +------+------------------------+ | 1 | 1090 | 202 | | 2 | 888 | 343 | | 3 | 545 | 111 | | 4 | 434 | 389 | | 5 | 45 | 45 |
我尝试过自我加入,但我不确定如何限制结果,而不是让它自行循环。我不能依赖于给定结果集的id值是顺序的,所以我没有使用那个值。我可以扩展架构以包含某种顺序值。
这是我尝试过的:
SELECT id, f.length, f2.length, (f.length - f2.length) AS difference FROM foo f, foo f2
感谢您的帮助。
答案 0 :(得分:13)
这可能会对您有所帮助。
select a.id, a.length,
coalesce(a.length -
(select b.length from foo b where b.id = a.id + 1), a.length) as diff
from foo a
答案 1 :(得分:6)
Yipee !!!这就是诀窍:
SELECT f.id, f.length,
(f.length - ISNULL(f2.length,0)) AS diff
FROM foo f
LEFT OUTER JOIN foo f2
ON f2.id = (f.id +1)
请检查其他情况,它适用于您发布的值! 请注意,这适用于SQL Server 2005
答案 2 :(得分:2)
所以他们只是从大到小排序?
SELECT f.id, f.length, (f.length - ISNULL(t.length, 0)) AS difference
FROM foo AS f
LEFT JOIN (
SELECT f1.id
,MAX(f2.length) as length
FROM foo AS f1
INNER JOIN foo AS f2
ON f1.length > f2.length
GROUP BY f1.id
) AS t -- this is the triangle
ON t.id = f.id
您可以将COALESCE
(或IFNULL
)代替ISNULL
用于MySQL。
答案 3 :(得分:1)
这样的事情:
SELECT T2.ID, T2.[Length], T2.[Length]-T1.[Length] AS 'Difference'
FROM Foo AS T1 RIGHT OUTER JOIN Foo AS T2 ON ( T1.ID = (T2.ID-1) )
ORDER BY T1.ID
答案 4 :(得分:1)
编辑:修复时重新阅读Q(被误解)
SELECT f.id,
f2.id,
f.length,
f2.length,
(f.length -f2.length) AS difference
FROM foo f,
foo f2
where f2.id = f.id+1
id含糊不清
编辑:注意:在mysql 5.0中测试
答案 5 :(得分:1)
Select f1.id, f1.seqnum, f2.seqnum, f1.length, f2.length, f1.length-f2.length
From (
Select Id, length, row_number(order by length) 'seqnum'
From
foo
) f1
Inner join (
Select
Id, length, row_number(order by length) 'seqnum' from foo union select 0, 0, 0
) f2
On f1.seqnum = f2.seqnum + 1
Order by f1.length desc
答案 6 :(得分:0)
我遇到了这个问题,看看你的解决方案很有意思。 我发现奇怪的是,这样的正常生活问题在SQL中是如此复杂。 由于我只需要报告中的值,我选择了一个完全不同的解决方案。 我正在运行Ruby on Rails作为我的sqlite3数据库的前端,并且只是在视图中进行了减法:
在ruby控制器中,有一个对象变量@foo,用于保存查询返回的行。
在视图中,只需执行
<table border=1>
<tr>
<th>id</th>
<th>length</th>
<th>difference</th>
</tr>
<% for i in 0..@foo.length-1 do %>
<tr>
<td><%=h @foo[i].id %></td>
<td><%=h @foo[i].length %></td>
<td><% if (i==@foo.length-1) then %>
<%= @foo[i].length %>
<% else %>
<%= @foo[i+1].length.to_i - @foo[i].length.to_i %>
<% end %>
</td>
</tr>
<% end %>
</table>
似乎比SQL解决方案更强大。