MySQL "Trending"

422 views Asked by At

I'm selecting "ideas" from my database currently, but another requirement is to be able to grab "trending ideas", that is, the top 10 most-up-voted ideas within the last 7 days.

My query for selecting "ideas" is this:

  SELECT
  t.id AS 'id',
  CONCAT(t.first_name, ' ', SUBSTRING(t.last_name,1,1)) AS 'name',
  t.votes_up,
  t.votes_down,
  t.votes_aggregate,
  GROUP_CONCAT(DISTINCT tags.name) AS 'tags',
  t.createdon AS 'timestamp'
  FROM (
    SELECT
      ideas.id, first_name, last_name, createdon,
      COALESCE(SUM(case when value > 0 then value end),0) votes_up,
      COALESCE(SUM(case when value < 0 then value end),0) votes_down,
      COALESCE(SUM(value),0) votes_aggregate
      FROM ideas
      LEFT JOIN votes ON ideas.id = votes.idea_id
      GROUP BY ideas.id
  ) as t
  LEFT JOIN tags_rel ON t.id = tags_rel.idea_id
  LEFT JOIN tags ON tags_rel.tag_id = tags.id

How would I get and display all the votes, but only get the "ideas" that have been voted up (votes_up) within the last 7 days and ordered by the amount of votes_up ?

This is my attempt:

  SELECT
      t.id AS 'id',
      CONCAT(t.first_name, ' ', SUBSTRING(t.last_name,1,1)) AS 'name',
      t.votes_up,
      t.votes_down,
      t.votes_aggregate,
      GROUP_CONCAT(DISTINCT tags.name) AS 'tags',
      t.createdon AS 'timestamp'
      FROM (
        SELECT
          ideas.id, first_name, last_name, createdon,
          COALESCE(SUM(case when value > 0 then value end),0) votes_up,
          COALESCE(SUM(case when value < 0 then value end),0) votes_down,
          COALESCE(SUM(value),0) votes_aggregate
          FROM ideas
          LEFT JOIN votes ON ideas.id = votes.idea_id
          GROUP BY ideas.id
      ) as t
      LEFT JOIN tags_rel ON t.id = tags_rel.idea_id
      LEFT JOIN tags ON tags_rel.tag_id = tags.id
  WHERE t.published = 1
  AND (
    SELECT ideas.id,
    COALESCE(SUM(case when value > 0 then value end),0) votes_up
    FROM ideas
    LEFT JOIN votes ON ideas.id = votes.idea_id
    WHERE votes.`timestamp` > (NOW() - INTERVAL 7 DAY)
    GROUP BY ideas.id
  ) as v
  GROUP BY t.id
  ORDER BY v.votes_up DESC

But I get the error for the right syntax to use near 'as v GROUP BY t.id ORDER BY v.votes_up DESC LIMIT 10'

2

There are 2 answers

3
davey On BEST ANSWER

You're using the 'AS v' in a WHERE clause, which isn't possible:

WHERE t.published = 1
  AND (
    SELECT ideas.id,
    COALESCE(SUM(case when value > 0 then value end),0) votes_up
    FROM ideas
    LEFT JOIN votes ON ideas.id = votes.idea_id
    WHERE votes.`timestamp` > (NOW() - INTERVAL 7 DAY)
    GROUP BY ideas.id
  ) as v
1
davey On

Try this one, in your SELECT statement you do the subquery, in your WHERE you check if this isn't NULL and you can order by it (if i'm right):

SELECT
      t.id AS 'id',
      CONCAT(t.first_name, ' ', SUBSTRING(t.last_name,1,1)) AS 'name',
      t.votes_up,
      t.votes_down,
      t.votes_aggregate,
      GROUP_CONCAT(DISTINCT tags.name) AS 'tags',
      t.createdon AS 'timestamp',
      (
         SELECT ideas.id,
         COALESCE(SUM(case when value > 0 then value end),0) votes_up
         FROM ideas
         LEFT JOIN votes ON ideas.id = votes.idea_id
         WHERE votes.`timestamp` > (NOW() - INTERVAL 7 DAY)
         GROUP BY ideas.id
      ) AS vup 
      FROM (
        SELECT
          ideas.id, first_name, last_name, createdon,
          COALESCE(SUM(case when value > 0 then value end),0) votes_up,
          COALESCE(SUM(case when value < 0 then value end),0) votes_down,
          COALESCE(SUM(value),0) votes_aggregate
          FROM ideas
          LEFT JOIN votes ON ideas.id = votes.idea_id
          GROUP BY ideas.id
      ) as t
      LEFT JOIN tags_rel ON t.id = tags_rel.idea_id
      LEFT JOIN tags ON tags_rel.tag_id = tags.id
  WHERE t.published = 1
  AND vup IS NOT NULL
  GROUP BY t.id
  ORDER BY vup DESC