質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

2回答

2101閲覧

テーブル内での従属関係を一括選択あるいは削除したい

SatoshiM

総合スコア12

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

1グッド

0クリップ

投稿2016/10/15 09:09

以下のような従属関係を表すテーブルにおいて、従属する配下の従属関係のあるレコードも選択、削除することは可能でしょうか。

上司='上田一郎'を指定した場合、行1,2,3,6を一括選択、削除したいのです。実際には複数のキーで実装する予定です。よろしくお願いします。

行 上司 部下
1 上田一郎 東田二郎
2 上田一郎 西田四郎
3 東田二郎 山田三郎
4 佐藤幸一 鈴木康二
5 佐藤幸一 井上幸三
6 山田三郎 北田四郎

KiyoshiMotoki👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

利用されているRDBがわからないので一般的な答えですが、以下のページを参考に。

津島博士のパフォーマンス講座|第31回 再帰的問合せについて

投稿2016/10/15 10:17

A-pZ

総合スコア12011

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SatoshiM

2016/10/17 01:26

回答ありがとうございます! SQLServerです。 再帰CTEが使えそうとは思っていたのですが、今一つ確信が持てずにいました。こちらをじっくり読ませていただきます。
guest

0

ベストアンサー

ひとつのDBのmysqlで簡単なストアドを作成してみました

mysql

1#tabel定義 2create table tableA (id int, joshi text, buka text); 3 4#ストアド 5DELIMITER // 6CREATE PROCEDURE sample03 ( IN in_name TEXT ) 7BEGIN 8 9DECLARE _done int; 10DECLARE _joshi_name TEXT; 11DECLARE _buka_name TEXT; 12DECLARE cur CURSOR FOR 13 SELECT joshi, buka FROM tableA WHERE joshi=in_name; 14DECLARE EXIT HANDLER FOR NOT FOUND SET _done = 0; 15 16SET _done = 1; 17OPEN cur; 18WHILE _done DO 19 FETCH cur INTO _joshi_name, _buka_name; 20 CALL sample03 (_buka_name); 21 DELETE FROM tableA WHERE joshi=_joshi_name AND buka=_buka_name; 22END WHILE; 23CLOSE cur; 24 25END 26// 27DELIMITER ; 28 29 30#実行 31set max_sp_recursion_depth=12; 32CALL sample03 ('上田一郎');

postgresでも作成してみました。指定された上司のレコードから、上司部下の関係のテーブルを最深階層(部下がいない)までを読み、そこから逆に上に戻りながら削除を行う動きとなります。

postgres

1#ストアド 2CREATE OR REPLACE FUNCTION test_sp_func9(in_name TEXT) 3RETURNS INT AS $$ 4 5DECLARE rc tableA%rowtype; 6DECLARE _ret int; 7BEGIN 8 9 FOR rc IN SELECT * FROM tableA WHERE joshi=in_name LOOP 10 SELECT test_sp_func9 (rc.buka) INTO _ret; 11 DELETE FROM tableA WHERE joshi=rc.joshi AND buka=rc.buka; 12 END LOOP; 13 RETURN 0; 14 15END; 16$$ LANGUAGE plpgsql; 17 18#実行 19select test_sp_func9('上田一郎');

SqlServerも作成しました。久々で自信はありませんが、動く様です。

WITH EMP_CTE(id, jyoshi, buka) AS ( SELECT id, jyoshi, buka FROM testAA WHERE jyoshi = '上田一郎' UNION ALL SELECT testAA.id, testAA.jyoshi, testAA.buka FROM testAA INNER JOIN EMP_CTE ON testAA.jyoshi = EMP_CTE.buka ) -- DELETE FROM testAA WHERE id in (SELECT id FROM EMP_CTE);

投稿2016/10/16 04:26

編集2016/10/19 04:38
A.Ichi

総合スコア4070

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SatoshiM

2016/10/17 01:33

回答ありがとうございます! mysqlは環境が無くて試せていません。 ざっと、拝見するとこれでは1,2は削除できても、配下の3,6は削除できないのではないでしょうか?
A.Ichi

2016/10/17 17:37

リカーシブル(再帰)により削除されると思います。一応テストはしました。DBは何をお持ちでしょうか?
SatoshiM

2016/10/18 11:43

postgresでもありがとうございます。恐縮です。 DBはMS-SQLServerです。ストアドで再帰できるんですね!
SatoshiM

2016/10/19 06:41 編集

A.Ichoさん、SQLServerでも回答いただき、誠にありがとうございました。 回答を参考に、id無しで以下の様に改造して、動作確認しました! ```SQL WITH 上司部下_CTE(上司, 部下) AS ( SELECT a.上司, a.部下 FROM 上司部下 a WHERE a.上司 = '上田一郎' UNION ALL SELECT b.上司, b.部下 FROM 上司部下 b INNER JOIN 上司部下_CTE c ON b.上司 = c.部下 ) DELETE FROM 上司部下 WHERE 上司 in (SELECT 上司 FROM 上司部下_CTE); ```
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問