いくつかの行のデータがあるSQLに困惑していて、前の行から1行を減算して、最後まで繰り返してもらいたいと思っています。
だからここに表があります:
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)
結果に、差分と呼ばれる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 Difference FROM foo f、foo f2
助けてくれてありがとう。
これは(ある程度)役立つかもしれません。
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
イピー!!!これはトリックを行います:
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用であることに注意してください
それで、彼らはただ最大から最小に注文されますか?
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
の代わりにIFNULL
(またはISNULL
)を使用できます。
このようなものはどうですか?
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
編集: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でテスト済み
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
私はこの問題を抱えていました、そしてあなたの解決策を見るのは面白かったです。このような通常の問題がSQLで非常に複雑であるのは奇妙だと思います。レポートの値のみが必要なため、まったく異なるソリューションを選択しました。 sqlite3データベースのフロントエンドとしてRuby on Railsを実行していて、次のようなビューで減算を実行しました。
Rubyコントローラーには、クエリによって返された行を保持するオブジェクト変数@fooがあります。
ビューでは、
<table border=1>
<tr>
<th>id</th>
<th>length</th>
<th>difference</th>
</tr>
<% for i in [email protected] do %>
<tr>
<td><%=h @foo[i].id %></td>
<td><%=h @foo[i].length %></td>
<td><% if ([email protected]) then %>
<%= @foo[i].length %>
<% else %>
<%= @foo[i+1].length.to_i - @foo[i].length.to_i %>
<% end %>
</td>
</tr>
<% end %>
</table>
SQLソリューションよりも堅牢なようです。