استفسار:حساب مجاميع متعددة لكل عنصر
-
07-07-2019 - |
سؤال
غالبًا ما تحتاج إلى إظهار قائمة بعناصر قاعدة البيانات وأرقام مجمعة معينة حول كل عنصر.على سبيل المثال، عند كتابة نص العنوان في Stack Overflow، تظهر قائمة الأسئلة ذات الصلة.تعرض القائمة عناوين الإدخالات ذات الصلة والعدد المجمع الفردي لكمية الردود لكل عنوان.
لدي مشكلة مماثلة ولكن بحاجة إلى مجاميع متعددة.أرغب في عرض قائمة بالعناصر بأي من التنسيقات الثلاثة حسب خيارات المستخدم:
- اسم العنصر الخاص بي (إجمالي 15، 13 مملوكة لي)
- اسم العنصر الخاص بي (إجمالي 15)
- اسم السلعة الخاصة بي (13 مملوكة لي)
قاعدة البيانات الخاصة بي هي:
- أغراض:معرف العنصر، اسم العنصر، معرف المالك
- فئات:معرف القط، اسم القط
- خريطة:معرف الخريطة، معرف العنصر، معرف القط
الاستعلام أدناه يحصل على:اسم الفئة، عدد معرفات العناصر لكل فئة
SELECT
categories.catName,
COUNT(map.itemId) AS item_count
FROM categories
LEFT JOIN map
ON categories.catId = map.catId
GROUP BY categories.catName
هذا واحد يحصل على:اسم الفئة، عدد معرفات العناصر لكل فئة لمعرف_المالك هذا فقط
SELECT categories.catName,
COUNT(map.itemId) AS owner_item_count
FROM categories
LEFT JOIN map
ON categories.catId = map.catId
LEFT JOIN items
ON items.itemId = map.itemId
WHERE owner = @ownerId
GROUP BY categories.catId
ولكن كيف يمكنني الحصول عليها في نفس الوقت في استعلام واحد؟أي.:اسم الفئة، عدد معرفات العناصر لكل فئة، عدد معرفات العناصر لكل فئة لمعرف_المالك هذا فقط
علاوة.كيف يمكنني اختياريًا استرداد رقم catId فقط!= 0 لأي من هذه العناصر؟في تجربة "WHERE item_count <> 0" أحصل على:
MySQL said: Documentation
#1054 - Unknown column 'rid_count' in 'where clause'
المحلول
إليك خدعة:حساب أ SUM()
من القيم المعروفة بأنها إما 1 أو 0 تعادل a COUNT()
من الصفوف التي تكون القيمة فيها 1.وأنت تعلم أن المقارنة المنطقية ترجع 1 أو 0 (أو NULL).
SELECT c.catname, COUNT(m.catid) AS item_count,
SUM(i.ownerid = @ownerid) AS owner_item_count
FROM categories c
LEFT JOIN map m USING (catid)
LEFT JOIN items i USING (itemid)
GROUP BY c.catid;
بالنسبة لسؤال المكافأة، يمكنك ببساطة إجراء صلة داخلية بدلاً من صلة خارجية، مما يعني فقط الفئات التي تحتوي على صف واحد على الأقل map
سيتم إرجاعها.
SELECT c.catname, COUNT(m.catid) AS item_count,
SUM(i.ownerid = @ownerid) AS owner_item_count
FROM categories c
INNER JOIN map m USING (catid)
INNER JOIN items i USING (itemid)
GROUP BY c.catid;
إليك حل آخر، وهو ليس بنفس الكفاءة ولكنني سأعرضه لتوضيح سبب حصولك على الخطأ:
SELECT c.catname, COUNT(m.catid) AS item_count,
SUM(i.ownerid = @ownerid) AS owner_item_count
FROM categories c
LEFT JOIN map m USING (catid)
LEFT JOIN items i USING (itemid)
GROUP BY c.catid
HAVING item_count > 0;
لا يمكنك استخدام الأسماء المستعارة للأعمدة في WHERE
الشرط، لأن التعبيرات في WHERE
يتم تقييم الجملة قبل التعبيرات الموجودة في قائمة التحديد.بمعنى آخر، القيم المرتبطة بتعبيرات قائمة التحديد غير متوفرة بعد.
يمكنك استخدام الأسماء المستعارة للأعمدة في GROUP BY
, HAVING
, ، و ORDER BY
شروط.يتم تشغيل هذه الجمل بعد تقييم جميع التعبيرات الموجودة في قائمة التحديد.
نصائح أخرى
يمكنك التسلل إلى عبارة CASE داخل SUM() الخاص بك:
SELECT categories.catName,
COUNT(map.itemId) AS item_count,
SUM(CASE WHEN owner= @ownerid THEN 1 ELSE 0 END) AS owner_item_count
FROM categories
LEFT JOIN map ON categories.catId = map.catId
LEFT JOIN items ON items.itemId = map.itemId
GROUP BY categories.catId
HAVING COUNT(map.itemId) > 0
SELECT categories.catName,
COUNT(map.itemId) AS item_count,
COUNT(items.itemId) AS owner_item_count
FROM categories
INNER JOIN map
ON categories.catId = map.catId
LEFT JOIN items
ON items.itemId = map.itemId
AND items.owner = @ownerId
GROUP BY categories.catId
لاحظ أنه يمكنك استخدام أ HAVING
شرط على owner_item_count
, ، ولكن الصلة الداخلية تعتني بـ item_count نيابةً عنك.