سؤال

لدي الجداول التالية:
الشخص ، {"id" ، "name" ، "lastName"}
Sports ، {"id" "name" ، "type"}
Sportsperperson ، {"id" ، "personid" ، "SportsId"}

بالنسبة لاستعلامي ، أريد أن أحصل على جميع الأشخاص الذين يبررون رياضة محددة في حين أن لدي فقط سمة "الاسم" الرياضية تحت تصرفي. لاسترداد الصفوف الصحيحة ، اكتشفت الاستعلامات التالية:

SELECT *
FROM Person
WHERE Person.Id in 
(
    SELECT SportsPerPerson.PersonId FROM SportsPerPerson
    INNER JOIN Sports on SportsPerPerson.SportsId = Sports.Id
    WHERE Sports.Name = 'Tennis'
)
AND Person.Id in 
(
    SELECT SportsPerPerson.PersonId FROM SportsPerPerson
    INNER JOIN Sports on SportsPerPerson.SportsId = Sports.Id
    WHERE Sports.Name = 'Soccer'
)

أو

SELECT *
FROM Person
WHERE Id IN
    (SELECT PersonId FROM SportsPerPerson WHERE SportsId IN 
        (SELECT Id FROM Sports WHERE Name = 'Tennis'))
AND Id IN
    (SELECT PersonId FROM SportsPerPerson WHERE SportsId IN 
        (SELECT Id FROM Sports WHERE Name = 'Soccer'))

الآن سؤالي هو ، أليس هناك طريقة أسهل لكتابة هذا الاستعلام؟ استخدام فقط أو لن يعمل لأنني بحاجة إلى الشخص الذي يلعب "تنس" و "كرة قدم". ولكن باستخدام ولا يعمل أيضًا لأن القيم ليست على نفس الصف.

هل كانت مفيدة؟

المحلول

يجب عليك استخدام اثنين من الندوات في الاستعلام:

SELECT *
FROM Person p INNER JOIN SportsPerPerson spp1 ON (p.PersonId = spp1.PersonId)
              INNER JOIN Sports s1 ON (s1.SportsIN = spp1.SportId)
              INNER JOIN SportsPerPerson spp2 ON (p.PersonId = spp2.PersonId)
              INNER JOIN Sports s2 ON (s2.SportId = spp2.SportId)
    WHERE s1.Name = 'Tennis' AND s2.Name='Soccer'

نصائح أخرى

يمكنك استخدام آخر JOIN لتجنب الثانية IN. يعيد المجموعة الفرعية فقط هؤلاء الأشخاص الذين يلعبون كل من التنس وكرة القدم:

SELECT *
FROM Person
WHERE Person.Id IN
(
    SELECT spp1.PersonId
    FROM SportsPerPerson spp1
    JOIN SportsPerPerson spp2 ON ( spp2.PersonId = spp1.PersonId )
    JOIN Sports s1 on spp1.SportsId = s1.Id
    JOIN Sports s2 on spp2.SportsId = s2.Id
    WHERE s1.Name = 'Tennis'
      AND s2.Name = 'Soccer'
)

الحيلة هي استخدام الأسماء المستعارة حتى تتمكن من استخدام الجداول نفسها عدة مرات:

SELECT p.*
FROM Person p
INNER JOIN SportsPerPerson spa
  ON p.Id = spa.PersonId
INNER JOIN Sports sa
  ON spa.SportsId = sa.Id
INNER JOIN SportsPerPerson spb
  ON p.Id = spb.PersonId
INNER JOIN Sports sb
  ON spb.SportsId = sb.Id
WHERE
  sa.Name = 'Tennis'
  AND sb.Name = 'Soccer'

هذه:

SELECT  *
FROM    Person p
WHERE   (
        SELECT  COUNT(*)
        FROM    Sports s
        JOIN    SportsPerPerson sp
        ON      sp.SportsID = s.id
        WHERE   s.name IN ('Tennis', 'Soccer')
                AND sp.PersonID = p.id
        ) = 2

أو هذا:

SELECT  p.*
FROM    (
        SELECT  sp.PersonID
        FROM    Sports s
        JOIN    SportsPerPerson sp
        ON      sp.SportsID = s.id
        WHERE   s.name IN ('Tennis', 'Soccer')
        GROUP BY
                sp.PersonID
        HAVING  COUNT(*) = 2
        ) q
JOIN    person p
ON      p.id = q.personID

تحتاج إلى إعلان أ UNIQUE KEY أو أ PRIMARY KEY تشغيل SportsPerPerson (sportsid, personid) لهذا العمل بشكل صحيح وسريع.

الاستعلام الذي تحتاجه هو:

SELECT p.ID, p.Name, p.LastName
FROM Person p
JOIN SportsPerPerson sp ON p.ID = sp.PersonID 
JOIN Sports s ON sp.SportsID = s.ID
WHERE s.Name = 'Football'

ومع ذلك ، جانبا ، مفتاح المعرف على طاولة SportsPerperson ليس من الضروري تمامًا تنفيذ العديد من العلاقات التي لديك. سيكون استخدام الأعمدة الشخصية والرياضية كمفتاح أساسي مركب كافيًا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top