LoginSignup
kunusann
@kunusann

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

SQLiteのupdate文で、特定のカラムの昇順で並べてから更新したいです

解決したいこと

SQLiteでupdate文中にorder byを使おうと思ったのですが、SQLiteでは出来ないようです。特定のカラムの順序で並べたテーブルを更新する方法を教えてください。

下記画像が使用しているテーブルです(見づらくてすみません。)
具体的には、positionカラムの昇順で並べてから、0, 1, 2, と+1ずつ増やしてpositionカラムを更新したいです。
image.png

自分で試したこと

updateにorder byを指定するのは、MySQLでは出来るそうですが、SQLiteではできないということは調べて分かりました。
image.png

ご回答よろしくお願いいたします。

0

2Answer

SQLiteで分析関数(window関数)が使えるバージョンでしたら以下のSQLでどうでしょうか?

UPDATE texts AS m SET position =
(
  SELECT Newposition - 1 
    FROM (SELECT _id
               , ROW_NUMBER() OVER (order by position) AS Newposition
            FROM texts
         ) 
  WHERE _id = m._id
); 

参考までに分析関数部分のみの実行結果は以下の通りです。

SELECT _id
     , ROW_NUMBER() OVER (order by position) AS Newposition
  FROM texts
_id Newposition
4 1
7 2
6 3


なお質問するときは、回答者が状況を再現しやすいように
SQL および 値の内容をテキストでコピーできるような方法で、なるべく回答者が回答しやすいようにお願いします。
おそらく私も@tetr4lab さんの回答がなければ回答することはなかったでしょう。

こちらでお試しできるようにしました
https://wandbox.org/permlink/Q40R24kkwipGRyHR

1

Comments

  1. @kunusann

    Questioner
    すみませんでした。今後の投稿では、コードを記載するようにします。
    分析関数という言葉を初めて聞き、勉強のきっかけにもなりました。ありがとうございました!
  2. お役にたてて何よりです。
    良かったですね。

詳しくないので、解釈から間違っている可能性もありそうなのですが、こういうやり方では解決にならないでしょうか?

課題

テーブルtextsに対する下記の処理をSQLで記述します。

処理前
_id text created_at position isChecked
4 s 2020-10-28 13:35:35 0 1
6 a 2020-10-28 13:35:46 4 1
7 k 2020-10-28 13:50:33 2 0
処理後
_id text created_at position isChecked
4 s 2020-10-28 13:35:35 0 1
6 a 2020-10-28 13:35:46 2 1
7 k 2020-10-28 13:50:33 1 0
課題の意味

position列の昇順に、0で始まる連番を振り直します。

考察

UPDATE texts AS m SET position = (
  SELECT COUNT(*) - 1 FROM texts 
  WHERE position <= m.position
);

このSQL文はエラーせずに完了しますが、課題は達成できず、position列は0, 2, 2になります。
これは、条件に使用してるテーブル(m)を書き替えてしまうためです。

ソートしたテーブルを更新することで回避できれば良いのですが、SQLiteではUPDATEORDER BYが使えないという問題が立ち塞がるわけですね。

一応の解決

少々トリッキーな方法ですが、テーブルにカラムtempを追加した上で、以下のSQLを実行するというのはいかがでしょうか。

UPDATE texts AS m SET temp = (
  SELECT COUNT(*) - 1 FROM texts 
  WHERE position <= m.position
);
UPDATE texts SET position = temp;
0

Comments

  1. takahasinaokiさんの回答が良さそうですね。
    そんな方法があるのですね。
    勉強になりました。
  2. @kunusann

    Questioner
    この方法でSQLite browserでは実行できました!ありがとうございました!
    (android studio側ではなぜかupdate文にasを用いるとコンパイルエラーとなって、成功できていないのですがこれは別の問題だと思います。)
  3. わざわざご確認いただきまして、ありがとうございます。
    こちらの方法は、ストレージを余分に使いますし、2文になるためトランザクション処理が必要になります。
    バージョンに制約がなければ、takahasinaokiさんの方法がスマートでお勧めですね。

Your answer might help someone💌