2009-10-28 5 views
2

J'ai été chargé de générer des rapports sur notre utilisation de Request Tracker. Request Tracker est un système de billetterie que nous utilisons pour plusieurs départements où je travaille. Pour ce faire, je prends un instantané nocturne des détails sur les billets modifiés pour la journée dans une autre base de données. Cette approche dissocie mes rapports du schéma de base de données interne utilisé par RT. Parmi les nombreuses autres questions du rapport, je dois signaler le nombre de tickets résolus chaque mois par département. Dans RT, le département est stocké en tant que CustomField, et ma modélisation suit cette tendance, comme vous pouvez le voir dans ma requête ci-dessous. Cependant, en raison de la façon dont je saisis des instantanés chaque nuit, j'ai plusieurs lignes pour un ticket, et le champ Département peut changer au cours du mois. Je ne suis intéressé que par le domaine le plus récent du département. Je ne sais pas comment l'obtenir dans une requête. Je sais que je peux utiliser 'GROUP BY' pour réduire mes résultats de requête à un par ticket, mais quand je le fais, je ne sais pas comment saisir le dernier paramètre de département. Comme les départements sont tous des chaînes, un MAX() n'obtient pas le dernier. MySQL ne vous oblige pas à utiliser une fonction d'agrégation pour les champs que vous sélectionnez, mais les résultats sont indéterminés (d'après mes tests, il semblerait que cela puisse prendre le premier sur ma version de MySQL).Sélection de la dernière chaîne lors de l'agrégation des résultats dans mysql

Pour illustrer, voici les résultats d'une requête qui me montre deux billets, et tous ses paramètres sur le terrain Département:

"ticket_num","date","QueueName","CF","CFValue","closed" 
35750,"2009-09-22","IT_help","Department","","" 
35750,"2009-09-23","IT_help","Department","","" 
35750,"2009-09-24","IT_help","Department","","" 
35750,"2009-09-25","IT_help","Department","","" 
35750,"2009-09-26","IT_help","Department","","" 
35750,"2009-10-02","IT_help","Department","","" 
35750,"2009-10-03","IT_help","Department","","" 
35750,"2009-10-12","IT_help","Department","","" 
35750,"2009-10-13","IT_help","Department","","" 
35750,"2009-10-26","IT_help","Department","Conference/Visitors","2009-10-26 10:10:32" 
35750,"2009-10-27","IT_help","Department","Conference/Visitors","2009-10-26 10:10:32" 
36354,"2009-10-20","IT_help","Department","","" 
36354,"2009-10-21","IT_help","Department","","" 
36354,"2009-10-22","IT_help","Department","FS Students","" 
36354,"2009-10-23","IT_help","Department","FS Students","" 
36354,"2009-10-26","IT_help","Department","FS Students","2009-10-26 12:23:00" 
36354,"2009-10-27","IT_help","Department","FS Students","2009-10-26 12:23:00" 

Comme on peut le voir, les deux billets ont été fermés le 26 et les billets avait un champ de département vide pendant quelques jours quand ils sont apparus. J'ai inclus ma requête ci-dessous, vous pouvez voir que j'ai artificiellement limité le nombre de colonnes est retourné dans la seconde moitié de la déclaration où:

SELECT d.ticket_num, d.date, q.name as QueueName, cf.name as CF, cfv.value as CFValue, d.closed 
FROM daysCF dcf 
INNER JOIN daily_snapshots d on dcf.day_id = d.id 
INNER JOIN Queues q on d.queue_id = q.id 
INNER JOIN CustomFieldValues cfv on dcf.cfv_id = cfv.id 
INNER JOIN CustomFields cf on cf.id = cfv.field_id 
WHERE cf.name = 'Department' and (d.ticket_num = 35750 or d.ticket_num = 36354) 
ORDER by d.ticket_num, d.date 

Comment puis-je modifier cette requête si je reçois un jeu de résultats cela me dit qu'en octobre il y avait un ticket fermé pour "FS Students" et un ticket fermé pour "Conference/Visitors"?

Répondre

0

Il s'agit du problème le plus important par groupe survenant fréquemment dans Stack Overflow.

Voilà comment je résous dans votre cas:

SELECT d1.ticket_num, d1.date, q.name as QueueName, 
    cf.name as CF, cfv.value as CFValue, d1.closed 
FROM daysCF dcf 
INNER JOIN daily_snapshots d1 ON (dcf.day_id = d1.id) 
INNER JOIN Queues q ON (d1.queue_id = q.id) 
INNER JOIN CustomFieldValues cfv ON (dcf.cfv_id = cfv.id) 
INNER JOIN CustomFields cf ON (cf.id = cfv.field_id) 
LEFT OUTER JOIN daily_snapshots d2 ON (d1.ticket_num = d2.ticket_num AND d1.date < d2.date) 
WHERE d2.id IS NULL AND cf.name = 'Department' 
ORDER by d1.ticket_num, d1.date; 
+0

que doit LEFT OUTER JOIN fin avec '... ET d1.date

+0

Oui, vous avez raison. Désolé pour la faute de frappe, je l'ai réparé. –

0

Mysql n'a pas d'opérateur LAST, vous devez donc le faire en utilisant une table temporaire.

CREATE TEMPORARY TABLE last_dates SELECT ticket_num, MAX(date) AS date 
    FROM daily_snapshots GROUP BY ticket_num 

qui vous obtient un tableau avec la dernière date pour chaque ticket. Ensuite, dans votre requête principale, rejoignez cette table avec les champs ticket_num et date. Cela filtrera toutes les lignes pour lesquelles la date n'est pas la dernière pour le numéro de ticket correspondant.

Vous pourriez avoir besoin d'un index sur cette table temporaire, je vous laisse cela.

Questions connexes