12

我被一些 SQL 难住了,我有几行数据,我想从前一行中减去一行,并让它一直重复下去。

所以这里是表格:

创建表 foo (
  ID,
  长度
)
插入 foo (id,length) VALUES(1,1090)
插入 foo (id,length) 值 (2,888)
插入 foo (id,length) 值 (3,545)
插入 foo (id,length) 值 (4,434)
插入 foo (id,length) VALUES(5,45)

我希望结果显示称为差异的第三列,它是从下面的一行中减去一行,最后一行从零中减去。

+--------+-------------+
| 编号 |长度 | 区别 |
+--------+-------------+
| 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 差异
FROM 富 f, 富 f2

谢谢你的帮助。

4

7 回答 7

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

于 2009-05-28T04:15:40.863 回答
7

伊皮!!!这可以解决问题:

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

于 2009-05-28T04:18:08.980 回答
3

所以他们只是从大到小排序?

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(or IFNULL) 代替ISNULLMySQL。

于 2009-05-28T04:18:38.873 回答
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
于 2009-05-28T04:15:47.400 回答
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 中测试

于 2009-05-28T04:17:32.147 回答
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
于 2009-05-28T04:30:45.463 回答
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 解决方案更健壮。

于 2010-04-02T17:42:48.697 回答