teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

6

推敲

2020/01/15 06:57

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -42,5 +42,5 @@
42
42
  ,(3, 'ミカン', '2019/01/31 10:01:01')
43
43
  ,(4, 'なし' , '2019/01/31 10:01:01')
44
44
  ;
45
- create index test_index on test2(id, last_update_time);
45
+ create index test_index on test2(id, name, last_update_time);
46
46
  ```

5

修正

2020/01/15 06:57

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -36,7 +36,7 @@
36
36
  一時テーブルを利用すれば排他も気にする必要はありません。
37
37
  ```SQL
38
38
  create temp table test2(id int, name text, last_update_time timestamp) on commit drop;
39
- insert into test values
39
+ insert into test2 values
40
40
  (1, 'ぶどう', '2019/01/01 01:01:01')
41
41
  ,(2, 'バナナ', '2019/01/31 10:01:01')
42
42
  ,(3, 'ミカン', '2019/01/31 10:01:01')

4

追記

2020/01/15 06:55

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -30,4 +30,17 @@
30
30
  INSERT INTO test tgt SELECT * FROM test2 src
31
31
  WHERE not exists(select 1 from test where id=src.id)
32
32
  ;
33
+ ```
34
+
35
+ 高速にするポイントは、更新対象データをテーブルデータにする事です。
36
+ 一時テーブルを利用すれば排他も気にする必要はありません。
37
+ ```SQL
38
+ create temp table test2(id int, name text, last_update_time timestamp) on commit drop;
39
+ insert into test values
40
+ (1, 'ぶどう', '2019/01/01 01:01:01')
41
+ ,(2, 'バナナ', '2019/01/31 10:01:01')
42
+ ,(3, 'ミカン', '2019/01/31 10:01:01')
43
+ ,(4, 'なし' , '2019/01/31 10:01:01')
44
+ ;
45
+ create index test_index on test2(id, last_update_time);
33
46
  ```

3

追記

2020/01/15 06:54

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -18,4 +18,16 @@
18
18
  and not exists(select 1 from test where id=src.id)
19
19
  ```
20
20
 
21
- ですが、レスポンスを考えるなら、updateとinsertをそれぞれで行った方が高速です。
21
+ ですが、レスポンスを考えるなら、updateとinsertをそれぞれで行った方が高速です。
22
+ ```SQL
23
+ UPDATE test tgt SET
24
+ name=val.name
25
+ , last_update_time=val.last_update_time
26
+ FROM test2 val
27
+ WHERE tgt.id=val.id
28
+ and (tgt.name!=val.name or tgt.last_update_time!=val.last_update_time)
29
+ ;
30
+ INSERT INTO test tgt SELECT * FROM test2 src
31
+ WHERE not exists(select 1 from test where id=src.id)
32
+ ;
33
+ ```

2

追記

2020/01/15 06:50

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -13,7 +13,9 @@
13
13
  and (tgt.name!=val.name or tgt.last_update_time!=val.last_update_time)
14
14
  returning tgt.*
15
15
  )
16
+ INSERT INTO test tgt SELECT * FROM test2 src
16
- INSERT INTO test SELECT * FROM test2 WHERE id NOT IN (SELECT id FROM upd)
17
+ WHERE id NOT IN (SELECT id FROM upd)
18
+ and not exists(select 1 from test where id=src.id)
17
19
  ```
18
20
 
19
21
  ですが、レスポンスを考えるなら、updateとinsertをそれぞれで行った方が高速です。

1

推敲

2020/01/15 06:47

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -1,6 +1,6 @@
1
1
  > 実現する為にSQL一本で可能かどうか
2
2
 
3
- with式とreturninを活用すれば可能です。
3
+ with式と[returning](https://www.postgresql.jp/document/11/html/dml-returning.html)を活用すれば可能です。
4
4
 
5
5
  下記は、対象のテーブルをtest、データをワーク(一時テーブルなど)に格納した更新用データをtest2として記述しています。
6
6
  ```SQL