sql >> Database >  >> RDS >> Mysql

MySQL SELECT meest frequent per groep

SELECT t1.*
FROM (SELECT tag, category, COUNT(*) AS count
      FROM tags INNER JOIN stuff USING (id)
      GROUP BY tag, category) t1
LEFT OUTER JOIN 
     (SELECT tag, category, COUNT(*) AS count
      FROM tags INNER JOIN stuff USING (id)
      GROUP BY tag, category) t2
  ON (t1.tag = t2.tag AND (t1.count < t2.count 
      OR t1.count = t2.count AND t1.category < t2.category))
WHERE t2.tag IS NULL
ORDER BY t1.count DESC;

Ik ben het ermee eens dat dit een beetje te veel is voor een enkele SQL-query. Elk gebruik van GROUP BY binnen een subquery doet me huiveren. Je kunt het eruit laten zien eenvoudiger door weergaven te gebruiken:

CREATE VIEW count_per_category AS
    SELECT tag, category, COUNT(*) AS count
    FROM tags INNER JOIN stuff USING (id)
    GROUP BY tag, category;

SELECT t1.*
FROM count_per_category t1
LEFT OUTER JOIN count_per_category t2
  ON (t1.tag = t2.tag AND (t1.count < t2.count 
      OR t1.count = t2.count AND t1.category < t2.category))
WHERE t2.tag IS NULL
ORDER BY t1.count DESC;

Maar achter de schermen doet het eigenlijk hetzelfde werk.

U merkt op dat u een vergelijkbare bewerking gemakkelijk in de toepassingscode zou kunnen uitvoeren. Dus waarom doe je dat niet? Voer de eenvoudigere zoekopdracht uit om de tellingen per categorie te krijgen:

SELECT tag, category, COUNT(*) AS count
FROM tags INNER JOIN stuff USING (id)
GROUP BY tag, category;

En sorteer het resultaat in de applicatiecode.



  1. php, mysql - Te veel verbindingen met databasefout

  2. Oracle-XMLTYPE:een waarde bijwerken

  3. Codeigniter simple_query vs. query builder (invoegen, bijwerken en verwijderen)

  4. Haal de datum/tijd uit een Unix-tijdstempel in SQLite