كيو - يرتبط الفرعية الاستعلام تفشل ؟
-
06-07-2019 - |
سؤال
لدي سؤال مثل هذا:
SELECT t1.id,
(SELECT COUNT(t2.id)
FROM t2
WHERE t2.id = t1.id
) as num_things
FROM t1
WHERE num_things = 5;
الهدف هو الحصول على معرف جميع العناصر التي تظهر 5 مرات في الجدول الآخر.ولكن يمكنني الحصول على هذا الخطأ:
ERROR: column "num_things" does not exist
SQL state: 42703
أنا ربما تفعل شيئا سخيفا هنا ، أنا جديدة إلى حد ما إلى قواعد البيانات.هل هناك طريقة لإصلاح هذا الاستعلام حتى أستطيع الوصول num_things
?أو إذا لم يكن هناك أي وسيلة أخرى لتحقيق هذه النتيجة ؟
المحلول
وأعتقد أنك يمكن أن مجرد كتابة الاستعلام الخاص بك مثل ذلك:
SELECT t1.id
FROM t1
WHERE (SELECT COUNT(t2.id)
FROM t2
WHERE t2.id = t1.id
) = 5;
نصائح أخرى
بعض النقاط الهامة حول استخدام SQL:
- لا يمكنك استخدام عمود الأسماء المستعارة في جملة WHERE, ولكن يمكن في وجود الشرط.هذا هو سبب الخطأ لديك.
- يمكنك القيام بعملك أفضل باستخدام الانضمام إلى المجموعة من خلال استخدام يرتبط الاستعلامات الفرعية.سيكون أسرع بكثير.
- استخدام وجود بند تصفية المجموعات.
هذه هي الطريقة التي كنت أكتب هذا الاستعلام:
SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;
أنا أدرك هذا الاستعلام يمكن تخطي JOIN
مع t1 ، كما في تشارلز Bretana الحل.ولكن أفترض أنك قد تريد الاستعلام لتشمل بعض الأعمدة الأخرى من t1.
Re:السؤال في التعليق:
الفرق هو أن WHERE
شرط يتم تقييم الصفوف قبل GROUP BY
يقلل من المجموعات على صف واحد لكل مجموعة.على HAVING
شرط تقييمها بعد أن يتم تشكيل مجموعات.لذا لا يمكنك ، على سبيل المثال ، تغيير COUNT()
مجموعة باستخدام HAVING
;يمكنك فقط استبعاد المجموعة نفسها.
SELECT t1.id, COUNT(t2.id) as num
FROM t1 JOIN t2 USING (id)
WHERE t2.attribute = <value>
GROUP BY t1.id
HAVING num > 5;
في الاستعلام ، WHERE
مرشحات صفوف مطابقة شرط ، HAVING
مرشحات المجموعات التي تضم خمسة على الأقل من العد.
النقطة التي تسبب معظم الناس الارتباك عندما لا يكون GROUP BY
شرط لذلك يبدو مثل HAVING
و WHERE
قابلة للتبادل.
WHERE
يتم تقييمها من قبل التعبيرات في اختيار القائمة.هذا قد لا يكون واضحا لأن بناء جملة SQL يضع اختر من القائمة الأولى.حتى تتمكن من توفير الكثير من تكلفة حساب باستخدام WHERE
لتقييد الصفوف.
SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;
إذا كنت تستخدم استعلام مثل ما ورد أعلاه ، التعبير في اختيار من القائمة المحسوبة كل صف, إلا أن تجاهل معظم النتائج بسبب HAVING
الشرط.ومع ذلك, الاستعلام أدناه يحسب التعبير فقط صف واحد مطابقة WHERE
الشرط.
SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;
لذلك باختصار, الاستعلامات يتم تشغيلها بواسطة مشغل قاعدة بيانات وفقا سلسلة من الخطوات:
- توليد مجموعة من الصفوف من الجدول(ق) ، بما في ذلك أي الصفوف التي تنتجها
JOIN
. - تقييم
WHERE
شروط ضد مجموعة من الصفوف ، تصفية الصفوف التي لا تتطابق. - حساب التعبيرات في تحديد قائمة لكل في مجموعة الصفوف.
- تطبيق عمود الأسماء المستعارة (ملاحظة هذا هو خطوة منفصلة ، مما يعني أنك لا يمكن استخدام الأسماء المستعارة في التعبير في اختيار من القائمة).
- تتكثف المجموعات صف واحد لكل مجموعة ، وفقا
GROUP BY
البند. - تقييم
HAVING
شروط ضد الجماعات تصفية الجماعات التي لا تتطابق. - نوع النتيجة ، وفقا
ORDER BY
البند.
جميع الاقتراحات الأخرى العمل، ولكن الإجابة عن السؤال الأساسي الخاص بك سيكون كافيا لكتابة
SELECT id From T2
Group By Id
Having Count(*) = 5
وأود أن أذكر أن في كيو لا توجد وسيلة لاستخدام العمود مستعارة في وجود الشرط.
وأي بمعنى.
وSELECT usr_id AS my_id من يضطر المستخدم my_id = 1
والعمل متعود.
والمثال الآخر الذي لن تعمل:
وsu.usr_id SELECT AS my_id، COUNT (*) AS فال من sys_user AS سو GROUP BY su.usr_id بصعوبات فال => 1
وسوف يكون هناك نفس الخطأ: لا يعرف العمود فال
وايم highliting هذا لبيل Karwin كتبت شيئا غير صحيح حقا لبوستجرس:
و"لا يمكنك استخدام الأسماء المستعارة العمود في جملة WHERE، ولكن يمكنك في جملة HAVING. هذا هو سبب الخطأ الذي حصلت عليه."
وهذه محاولة
SELECT t1.id,
(SELECT COUNT(t2.id) as myCount
FROM t2
WHERE t2.id = t1.id and myCount=5
) as num_things
FROM t1