join - انضمام SQL:حيث جملة مقابل جملة




where-clause on-clause (13)

على صلة داخلية ، فإنها تعني نفس الشيء. ومع ذلك ، ستحصل على نتائج مختلفة في صلة خارجية بناءً على ما إذا كنت وضعت شرط الربط في WHERE مقابل جملة ON. إلقاء نظرة على هذا السؤال ذات الصلة وهذه الإجابة (عن طريق لي).

أعتقد أنه من المنطقي أن تكون عادة في وضع شرط الربط في جملة ON (إلا إذا كانت صلة خارجية وكنت تريد بالفعل في مكان الجملة) لأنها تجعل الأمر أكثر وضوحًا لأي شخص يقرأ استعلامك. ما هي الشروط التي يتم الانضمام إليها في الجداول ، وأيضًا تساعد في منع جملة WHERE من أن تكون عشرات الأسطر طويلة.

بعد قراءته ، هذا ليس مكررًا لـ Explicit vs Implicit SQL Joins . قد تكون الإجابة مرتبطة (أو حتى نفسها) لكن السؤال مختلف.

ما هو الفرق وماذا يجب أن يحدث في كل منها؟

إذا فهمت النظرية بشكل صحيح ، فيجب أن يكون مُحسِّن الاستعلام قادرًا على استخدام كلٍّ منهما بالتبادل.


الطريقة التي أقوم بها هي:

ضع دائمًا شروط الانضمام في جملة الشرط إذا كنت تقوم بعمل صلة داخلية ، فلا تقم بإضافة أي شرط إلى العبارة الواردة ، ضعها في مكان الجملة

إذا كنت تقوم بعمل ارتباط يسار ، قم بإضافة أي شروط إلى عبارة on للجدول الموجود في الجانب الأيمن من الصلة. هذا أمر ضروري لأن إضافة جملة حيث تشير إلى الجانب الأيمن من الصلة سيتم تحويل الصلة إلى صلة داخلية (مع استثناء واحد هو موضح أدناه).

الاستثناء أنه عند البحث عن السجلات غير الموجودة في جدول معين ، يمكنك إضافة refernce إلى معرف فريد (لا أي قيمة فارغة) في جدول الربط الأيمن إلى حيث جملة بهذه الطريقة "Where t2. idfield فارغ ". لذا فإن الوقت الوحيد الذي ينبغي عليك فيه الرجوع إلى جدول على الجانب الأيمن من الصلة هو البحث عن السجلات غير الموجودة في الجدول.


  • لا يهم لالانضمام الداخلية
  • مسائل للانضمام الخارجي

    ا. WHERE شرط: بعد الانضمام. سيتم تصفية السجلات بعد الانضمام.

    ب. ON عبارة - قبل الانضمام. سيتم تصفية السجلات (من الجدول الأيمن) قبل الانضمام. قد ينتهي هذا كـ null في النتيجة (منذ انضمام OUTER).



مثال : النظر في الجداول أدناه:

    1. documents:
     | id    | name        |
     --------|-------------|
     | 1     | Document1   |
     | 2     | Document2   |
     | 3     | Document3   |
     | 4     | Document4   |
     | 5     | Document5   |


    2. downloads:
     | id   | document_id   | username |
     |------|---------------|----------|
     | 1    | 1             | sandeep  |
     | 2    | 1             | simi     |
     | 3    | 2             | sandeep  |
     | 4    | 2             | reya     |
     | 5    | 3             | simi     |

أ) في WHERE :

  SELECT documents.name, downloads.id
    FROM documents
    LEFT OUTER JOIN downloads
      ON documents.id = downloads.document_id
    WHERE username = 'sandeep'

 For above query the intermediate join table will look like this.

    | id(from documents) | name         | id (from downloads) | document_id | username |
    |--------------------|--------------|---------------------|-------------|----------|
    | 1                  | Document1    | 1                   | 1           | sandeep  |
    | 1                  | Document1    | 2                   | 1           | simi     |
    | 2                  | Document2    | 3                   | 2           | sandeep  |
    | 2                  | Document2    | 4                   | 2           | reya     |
    | 3                  | Document3    | 5                   | 3           | simi     |
    | 4                  | Document4    | NULL                | NULL        | NULL     |
    | 5                  | Document5    | NULL                | NULL        | NULL     |

  After applying the `WHERE` clause and selecting the listed attributes, the result will be: 

   | name         | id |
   |--------------|----|
   | Document1    | 1  |
   | Document2    | 3  | 

ب) داخل جملة JOIN

  SELECT documents.name, downloads.id
  FROM documents
    LEFT OUTER JOIN downloads
      ON documents.id = downloads.document_id
        AND username = 'sandeep'

For above query the intermediate join table will look like this.

    | id(from documents) | name         | id (from downloads) | document_id | username |
    |--------------------|--------------|---------------------|-------------|----------|
    | 1                  | Document1    | 1                   | 1           | sandeep  |
    | 2                  | Document2    | 3                   | 2           | sandeep  |
    | 3                  | Document3    | NULL                | NULL        | NULL     |
    | 4                  | Document4    | NULL                | NULL        | NULL     |
    | 5                  | Document5    | NULL                | NULL        | NULL     |

Notice how the rows in `documents` that did not match both the conditions are populated with `NULL` values.

After Selecting the listed attributes, the result will be: 

   | name       | id   |
   |------------|------|
   |  Document1 | 1    |
   |  Document2 | 3    | 
   |  Document3 | NULL |
   |  Document4 | NULL | 
   |  Document5 | NULL | 

فيما يتعلق بالمحسِّن ، لا يجب أن يكون هناك فرق فيما إذا قمت بتحديد جمل الانضمام الخاصة بك مع ON أو WHERE.

ومع ذلك ، IMHO ، أعتقد أنه من الواضح أن استخدام جملة ON عند تنفيذ الصلات. بهذه الطريقة يكون لديك قسم محدد من استعلامك الذي يحدد كيفية معالجة الربط مقابل الاختلاط مع بقية عبارات WHERE.


هذا هو الحل الخاص بي.

SELECT song_ID,songs.fullname, singers.fullname
FROM music JOIN songs ON songs.ID = music.song_ID  
JOIN singers ON singers.ID = music.singer_ID
GROUP BY songs.fullname

يجب أن يكون لديك GROUP BY للحصول عليها للعمل.

نأمل أن تكون هذه المساعدة.


على INNER JOIN s ، فهي قابلة للتبديل ، وسيقوم المُحسِّن بإعادة ترتيبها حسب الرغبة.

على OUTER JOIN s ، فهي ليست بالضرورة قابلة للتبادل ، اعتمادًا على جانب الصلة التي تعتمد عليها.

أضعها في أي مكان اعتمادا على القراءة.


تشرح هذه المقالة الفرق بوضوح. يشرح أيضًا "ON joined_condition مقابل WHERE join_condition أو join_alias فارغ".

تقوم فقرة WHERE بتصفية كل من الجانب الأيمن والأيسر لـ JOIN ، بينما تعمل عبارة ON دائمًا على تصفية الجانب الأيمن فقط.

  1. إذا كنت ترغب دائمًا في جلب الصفوف الجانبية اليسرى ، ثم انضم فقط إذا تطابق بعض الشرط ، فيجب عليك استخدام جملة ON.
  2. إذا كنت ترغب في تصفية منتج الانضمام إلى كلا الجانبين ، فعليك استخدام جملة WHERE.

انهم ليسوا نفس الشيء.

خذ بعين الاعتبار هذه الاستعلامات:

SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID
WHERE Orders.ID = 12345

و

SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID 
    AND Orders.ID = 12345

الأول سيعرض طلبًا وخطوطه ، إن وجدت ، لطلب رقم 12345 . سوف يعيد الثاني جميع الطلبات ، ولكن فقط الترتيب 12345 سيكون له أي خطوط مرتبطة به.

مع INNER JOIN ، تكون الجمل مكافئة بشكل فعال . ومع ذلك ، لمجرد أنها نفس وظيفية ، في أنها تنتج نفس النتائج ، لا يعني أن هذين النوعين من العبارات لها نفس المعنى الدلالي.


للانضمام الداخلي ، يمكن استخدام WHERE و ON بالتبادل. في الواقع ، من الممكن استخدام ON في استعلام فرعي مترابط. فمثلا:

update mytable
set myscore=100
where exists (
select 1 from table1
inner join table2
on (table2.key = mytable.key)
inner join table3
on (table3.key = table2.key and table3.key = table1.key)
...
)

هذا (IMHO) محير للبشر ، ومن السهل جداً أن ننسى ربط table1 بأي شيء (لأن جدول "driver" لا يحتوي على جملة "on") ، ولكنه قانوني.


هناك اختلاف كبير بين مكان الجملة مقابل جملة ، عندما يتعلق الأمر بالانضمام إلى اليسار.

هذا مثال على ذلك:

mysql> desc t1; 
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| fid   | int(11)     | NO   |     | NULL    |       |
| v     | varchar(20) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+

هناك FID هو معرف الجدول t2.

mysql> desc t2;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| v     | varchar(10) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

الاستعلام عن "على فقرة":

mysql> SELECT * FROM `t1` left join t2 on fid = t2.id AND t1.v = 'K' 
    -> ;
+----+-----+---+------+------+
| id | fid | v | id   | v    |
+----+-----+---+------+------+
|  1 |   1 | H | NULL | NULL |
|  2 |   1 | B | NULL | NULL |
|  3 |   2 | H | NULL | NULL |
|  4 |   7 | K | NULL | NULL |
|  5 |   5 | L | NULL | NULL |
+----+-----+---+------+------+
5 rows in set (0.00 sec)

الاستعلام عن "مكان الجملة":

mysql> SELECT * FROM `t1` left join t2 on fid = t2.id where t1.v = 'K';
+----+-----+---+------+------+
| id | fid | v | id   | v    |
+----+-----+---+------+------+
|  4 |   7 | K | NULL | NULL |
+----+-----+---+------+------+
1 row in set (0.00 sec)

من الواضح أن الاستعلام الأول يقوم بإرجاع سجل من t1 والصف التابع التابع لها من t2 ، إن وجد ، للصف t1.v = 'K'.

يُرجع الاستعلام الثاني صفوف من t1 ، ولكن فقط لـ t1.v = 'K' سيكون له أي صف مرتبط به.


في SQL ، يكون البند "WHERE" و "ON" ، نوعًا من Statential Statitory ، لكن الفرق الرئيسي بينهما هو ، حيث يتم استخدام جملة Where في "Select / Update Statements" لتحديد الشروط ، في حين أن "ON" عبارة في عمليات الانضمام ، حيث يتحقق أو يتحقق مما إذا كانت السجلات متطابقة في جداول المصدر والهدف ، قبل انضمام الجداول

على سبيل المثال: - "أين

SELECT * FROM employee WHERE employee_id = 101

على سبيل المثال: - "ON"

* هناك نوعان من الجداول الموظف و staff_details ، أعمدة المطابقة هي employee_id. *

SELECT * FROM INNER JOIN employee_details ON employee.employee_id = employee_details.employee_id

آمل أن أكون قد أجبت على السؤال الخاص بك.راجع مرة أخرى للحصول على التوضيحات.


للحصول على جداول أداء أفضل يجب أن يكون لها عمود مفهرس خاص لاستخدامه في JOINS.

لذلك إذا كان العمود الذي قمت بوضعه ليس واحدًا من تلك الأعمدة المفهرسة ، فأعتقد أنه من الأفضل الاحتفاظ بها في WHERE.

لذا يمكنك الانضمام باستخدام الأعمدة المفهرسة ، ثم بعد JOIN ، يمكنك تشغيل الشرط في العمود بلا فهرسة.


وإذا كنت ترغب في الانضمام إلى الجدول نفسه (والذي لن يحدث في كثير من الأحيان):

update t1                    -- just reference table alias here
set t1.somevalue = t2.somevalue
from table1 t1               -- these rows will be the targets
inner join table1 t2         -- these rows will be used as source
on ..................        -- the join clause is whatever suits you




sql join where-clause on-clause