web-dev-qa-db-ja.com

自己結合の説明

私は自己結合の必要性を理解していません。誰かが私にそれらを説明してもらえますか?

簡単な例は非常に役立ちます。

自己結合は、2つの同一のテーブルとして表示できます。ただし、正規化では、テーブルのコピーを2つ作成することはできないため、自己結合のある2つのテーブルをシミュレートするだけです。

次の2つのテーブルがあるとします。

テーブル emp1

Id Name Boss_id            
1   ABC   3                   
2   DEF   1                   
3   XYZ   2                   

テーブル emp2

Id Name Boss_id            
1   ABC   3                   
2   DEF   1                   
3   XYZ   2                   

ここで、各従業員の名前を上司の名前で取得する場合:

select c1.Name , c2.Name As Boss
from emp1 c1
    inner join emp2 c2 on c1.Boss_id = c2.Id

次の表が出力されます。

Name  Boss
ABC   XYZ
DEF   ABC
XYZ   DEF
85

それ自体を参照するテーブルがある場合、それは非常に一般的です。例:すべての従業員がマネージャーを持つことができる従業員テーブルで、すべての従業員とそのマネージャーの名前をリストしたい場合。

SELECT e.name, m.name
FROM employees e LEFT OUTER JOIN employees m
ON e.manager = m.id
19
windyjonas

自己結合は、テーブルとそれ自体の結合です。

一般的なユースケースは、テーブルがそれらの間に階層関係を持つエンティティ(レコード)を格納する場合です。たとえば、個人情報(名前、DOB、住所...)を含み、父(および/または母)のIDが含まれる列を含むテーブル。次に、のような小さなクエリで

SELECT Child.ID, Child.Name, Child.PhoneNumber, Father.Name, Father.PhoneNumber
FROM myTableOfPersons As Child
LEFT OUTER JOIN  myTableOfPersons As Father ON Child.FatherId = Father.ID
WHERE Child.City = 'Chicago'  -- Or some other condition or none

同じクエリで、子と父親の両方(および、2番目の自己結合など、さらには親など)の両方に関する情報を取得できます。

17
mjv

テーブルusersがあり、次のように設定したとします。

  • ユーザーID
  • ユーザー名
  • ユーザーのマネージャーのID

この状況で、1つのクエリでユーザーの情報およびの両方の情報を引き出したい場合は、次のようにします。

SELECT users.user_id, users.user_name, managers.user_id AS manager_id, managers.user_name AS manager_name INNER JOIN users AS manager ON users.manager_id=manager.user_id
5
ceejayoz

テーブルが自己参照型の場合に便利です。たとえば、ページのテーブルの場合、各ページにはnextおよびpreviousリンクがあります。これらは、同じテーブル内の他のページのIDです。ある時点で連続したページのトリプルを取得したい場合、同じテーブルのnext列を持つprevious列とid列で2つの自己結合を実行します。

4
Max Shawabkeh

以下に説明するEmployeeというテーブルを想像してください。すべての従業員には従業員でもあるマネージャーがいます(おそらく、manager_idがヌルになるCEOを除く)

Table (Employee): 

int id,
varchar name,
int manager_id

その後、次の選択を使用して、すべての従業員とそのマネージャーを見つけることができます。

select e1.name, e2.name as ManagerName
from Employee e1, Employee e2 where
where e1.manager_id = e2.id

テーブルがそれ自体を参照する機能がない場合、階層レベルのテーブルを階層内のレイヤーの数と同じ数だけ作成する必要があります。しかし、その機能が利用可能であるため、テーブルをそれ自体に結合し、sqlはそれを2つの別個のテーブルとして扱います。そのため、すべてが1か所にうまく格納されます。

4
Eugene

ここには多くの正解がありますが、同様に正しいバリエーションがあります。 WHERE句の代わりに、結合ステートメントに結合条件を配置できます。

SELECT e1.emp_id AS 'Emp_ID'
  , e1.emp_name AS 'Emp_Name'
  , e2.emp_id AS 'Manager_ID'
  , e2.emp_name AS 'Manager_Name'
FROM Employee e1 RIGHT JOIN Employee e2 ON e1.emp_id = e2.emp_id

E1.manager_id> e2.idが必要な場合があることに留意してください

両方のシナリオを知ることの利点は、大量のWHERE条件またはJOIN条件があり、コードを読みやすくするために他の句に自己結合条件を配置したい場合があることです。

従業員にマネージャーがいない場合に何が起こるかについては誰も言及していません。え?結果セットには含まれません。マネージャーを持たない従業員を含めたいが、誤った組み合わせを返したくない場合はどうしますか?

この子犬をお試しください。

SELECT e1.emp_id AS 'Emp_ID'
   , e1.emp_name AS 'Emp_Name'
   , e2.emp_id AS 'Manager_ID'
   , e2.emp_name AS 'Manager_Name'
FROM Employee e1 LEFT JOIN Employee e2 
   ON e1.emp_id = e2.emp_id
   AND e1.emp_name = e2.emp_name
   AND e1.every_other_matching_column = e2.every_other_matching_column
3
BClaydon

自己結合は、テーブル自体のデータを評価する必要がある場合に役立ちます。つまり、同じテーブルの行を相互に関連付けます。

Syntax: SELECT * FROM TABLE t1, TABLE t2 WHERE t1.columnName = t2.columnName

たとえば、初期指定が現在の指定に等しい従業員の名前を検索するとします。次の方法で自己結合を使用してこれを解決できます。

SELECT NAME FROM Employee e1, Employee e2 WHERE e1.intialDesignationId = e2.currentDesignationId
1
Sumanth Varada

1つのユースケースは、データベース内の重複レコードをチェックすることです。

SELECT A.Id FROM My_Bookings A, My_Bookings B
WHERE A.Name = B.Name
AND A.Date = B.Date
AND A.Id != B.Id

これは、リンクリスト/ツリーに相当するデータベースであり、行には、ある容量の別の行への参照が含まれます。

0
Unsliced