어려운 SQL 쿼리 : 복잡한 연관성을 가진 모델에 대한 태그 인기

StackOverflow https://stackoverflow.com/questions/620788

  •  05-07-2019
  •  | 
  •  

문제

이것이 효율적으로 할 수 있는지 확실하지 않지만 여기 내 문제가 있습니다.

본인은 본질적으로 블로그 게시물과 각 블로그 게시물에 대한 모든 답변이 태그를 붙일 수있는 블로그 엔진을 작성하고 있습니다.

그래서 블로그 게시물에 "스택"태그가 붙어 있고 그 게시물에 대한 답변이 "오버 플로우"에 태그를 지을 수 있습니다.

지금은 사용자가 내 응용 프로그램에서 특별 페이지를 눌렀을 때 가장 인기있는 태그 목록을 생성하려고합니다. 블로그 게시물의 수를 내려 가면 가장 인기있는 태그뿐만 아니라 각 태그와 관련된 블로그 게시물 수를 반환해야합니다. 해당 게시물의 답변이 있지만 게시물 자체가 해당 태그로 태그가 지정되어 있어도.

따라서 BlogPost A가 "FOO"로 태그를 지정하고 BlogPost B의 답변에 "FOO"로 태그가 표시되면 BlogPost B가 기술적으로 태그되지 않더라도 인기있는 태그 요약은 총 2 개의 블로그 게시물로 계산해야합니다.

다음은 관련성이있는 테이블/필드에 대한 설명입니다.

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

편리함을 위해 태그에 약간의 비정규 화가 있습니다. 누군가가 블로그 포스트를 태그하면 blog_post_id 필드가 채워지고 blog_comment_id는 널 유지됩니다. 누군가가 게시물에 주석을 태그하면 blog_post_id 및 blog_comment_id를 모두 채 웁니다.

하나 또는 여러 SQL 쿼리에서 가장 인기있는 태그의 정렬 된 목록을 반환 할 수있는 방법이 있습니까? CRON 작업에서 몇 분마다 계산 저렴한 스크립트를 실행해야 할 수도 있고 누군가가 페이지를 때릴 때마다 실행하는 대신 캐시 된 출력을 렌더링해야 할 수도 있습니다.

감사!

도움이 되었습니까?

해결책

지금까지 나는 당신의 요청에 대해 복잡한 것이 없습니다.

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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top