12

いくつかの行のデータがあるSQLに困惑していて、前の行から1行を減算して、最後まで繰り返してもらいたいと思っています。

だからここに表があります:

CREATE TABLE foo(
  id、
  長さ
)。
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)

結果に、差分と呼ばれる3番目の列を表示します。これは、下の行から1行を減算し、最後の行をゼロから減算するものです。

+ ------ + ------------------------ +
| id|長さ| 違い|
+ ------ + ------------------------ +
| 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 foo f、foo 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

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)

他のケースもチェックしてください、あなたが投稿した値で動作しています!これはSQLServer2005用であることに注意してください

于 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

MySQLの代わりにCOALESCE(または)を使用できます。IFNULLISNULL

于 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があいまいでした

編集:注:mysql5.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で非常に複雑であるのは奇妙だと思います。レポートの値のみが必要なため、まったく異なるソリューションを選択しました。私はsqlite3データベースのフロントエンドとしてRubyonRailsを実行しており、次のようなビューで減算を実行しました。

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 に答える