صعب استعلام SQL:الوسم شعبية نماذج معقدة الجمعيات
سؤال
أنا لست حتى متأكدا من هذا من الممكن القيام به بكفاءة ، ولكن هنا مشكلتي:
أنا أكتب ما هو في الأساس محرك بلوق حيث بلوق وظيفة و كل الردود على كل بلوق وظيفة يمكن أن يوصف.
لذا أنا يمكن أن يكون لها بلوق وظيفة معلم "المكدس" ، ردا على هذا المنصب الموسومة "تجاوز".
الآن أنا أحاول إنشاء قائمة من العلامات الأكثر شعبية عندما يقوم المستخدم يضرب صفحة خاصة في التطبيق.وينبغي أن لا يعود فقط n الأكثر شعبية العلامات قبل نزول عدد من بلوق وظائف ، ولكن أيضا عدد من التدوينات المرتبطة مع بعضها العلامة ، حتى لو كان الرد في هذا المنصب ولكن ليس المنصب ذاته هو معلم مع هذا الوسم.
لذا ، إذا BlogPost هو ذات الكلمات الدلالية مع "فو" و رد في BlogPost ب هو معلم مع "فو" الشهيرة الوسم ملخص ينبغي اعتباره من اثنين من بلوق وظائف في مجموعه ، على الرغم من BlogPost ب ليس تقنيا الموسومة.
وهنا وصف الجداول/المجالات التي قد تكون ذات صلة:
BlogPosts
| id # Primary key for all tables, Rails-style
BlogComments
| id
| blog_post_id
Tags
| id
| name # 'foo'
Taggings
| id
| tag_id
| blog_post_id
| blog_comment_id
هناك بعض denormalization في Taggings أجل الراحة.إذا كان شخص ما العلامات BlogPost ، يملأ في blog_post_id المجال ، blog_comment_id يظل باطلا.إذا كان شخص ما العلامات تعليق على مشاركة, يملأ في كل blog_post_id و blog_comment_id.
هل هناك طريقة لإعادة فرز قائمة من العلامات الأكثر شعبية في واحد أو عدة استعلامات SQL?أنا أفكر أنا قد تحتاج إلى مجرد تشغيل حسابيا-تكلفة البرنامج النصي كل بضع دقائق على وظيفة كرون وتقديم الانتاج مؤقتا بدلا من تشغيل هذا في كل مرة شخص ما يضرب الصفحة...
وذلك بفضل!
المحلول
حتى الآن لا أرى أي شيء معقد في الطلب الخاص بك:
SELECT
tag_id,
COUNT(blog_post_id) + COUNT(blog_comment_id) tag_count
FROM
Taggings
GROUP BY
tag_id
ORDER BY
COUNT(blog_post_id) + COUNT(blog_comment_id) DESC
إذا كنت ترغب في الاعتماد المتضررة "التدوينات" فقط, أعتقد أن هذه هي الطريقة:
SELECT
t.id tag_id,
t.name tag_name,
COUNT(DISTINCT COALESCE(x.blog_post_id, c.blog_post_id)) tag_count
FROM
Tags t
INNER JOIN Taggings x ON x.tag_id = t.id
LEFT JOIN BlogComments c ON c.id = x.blog_comment_id
GROUP BY
t.id,
t.name
ORDER BY
COUNT(DISTINCT COALESCE(x.blog_post_id, c.blog_post_id)) DESC
نصائح أخرى
ربما أنا في عداد المفقودين شيء واضح ولكن لأن لديك "اذا كان هناك فئة تعليق على مشاركة, يملأ في كل blog_post_id و blog_comment_id", sql التالية ينبغي أن تفعل خدعة. أفترض هنا أن الكلمات.اسم هنا سوف تكون فريدة من نوعها.
SELECT MIN(ts.tag_id), t.name, COUNT(ts.blog_post_id) as rank
FROM Taggings ts
INNER JOIN Tags t ON ts.tag_id = t.id
GROUP BY t.name
ORDER BY COUNT(ts.blog_post_id) DESC
اتمنى ان يكون ما تبحث عنه.
لم حاولت ولكن ماذا عن شيء مثل هذا؟:
select t.Id,
t.Name,
count(*)
from Taggings tings
inner join Tags t
on (t.id = tings.blog_post_id or t.id = tings.blog_comment_id)
group by t.Id, t.Name
order by count(*) desc