2010-12-15 6 views
3

J'ai ceci:Faire une requête pour chaque jour dans une période, le transformant en une requête

public Map<Day,Integer> getUniqueLogins(long fromTime, long toTime) { 

    EntityManager em = emf.createEntityManager(); 
    try { 
    Map<Day,Integer> resultMap = new ...; 
    for (Day day : daysInPeriod(fromTime, toTime)) { 

    CriteriaBuilder cb = em.getCriteriaBuilder(); 
    CriteriaQuery<Long> q = cb.createQuery(Long.class); 

    // FROM UserSession 
    Root<UserSession> userSess = q.from(UserSession.class); 
    // SELECT COUNT(DISTINCT userId) 
    q.select(cb.countDistinct(userSess.<Long>get("userId"))); 
    // WHERE loginTime BETWEEN ... 
    q.where(cb.between(userSess.<Date>get("loginTime"), day.startDate(), day.endDate())); 

    long result = em.createQuery(q).getSingleResult(); 
    resultMap.put(day, (int) result); 
    } 
    return resultMap; 
    } finally { 
    em.close(); 
    } 

} 

Cette exécute une requête pour chaque jour dans une période donnée (la période étant de l'ordre de grandeur un mois).

Puis-je obtenir ces données spécifiques en une seule requête? J'utilise Hibernate/MySQL, mais je préfère ne pas avoir besoin de fonctions non standard.

Répondre

1

GROUP BY le segment de date de LoginTime comptant des ID utilisateur distincts. Le back-end doit fournir un moyen d'extraire la partie date de la valeur datetime.

2

En supposant que votre requête initiale est:

SELECT COUNT(DISTINCT userId) 
FROM UserSession 
WHERE loginTime BETWEEN dayStart AND dayEnd; 

Cela devrait retourner les mêmes résultats que l'exécution de l'original pour chaque jour de la période:

SELECT date(loginTime) AS day, COUNT(DISTINCT userId) 
FROM UserSession 
WHERE loginTime BETWEEN startDate AND endDate 
GROUP BY day; 
+0

Cela fonctionnerait, mais d'où vient cette fonction 'date'? Est-ce MySQL ou standard JPA/JPQL? Existe-t-il un équivalent dans l'API Criteria? –

+0

Je ne suis pas tout à fait sûr, mais je ne pense pas qu'il existe des fonctions de manipulation de date explicites dans le JPQL (autre que d'obtenir la date/heure actuelle). –

+0

Selon les docs, date() est une fonction MySQL qui renvoie la date d'une expression de date ou d'horodatage. http://dev.mysql.com/doc/refman/5.5/fr/date-and-time-functions.html#function_date –

1

Vous devez utiliser MySQL spécifique fonctions pour le faire.

SELECT FROM_DAYS(TO_DAYS(loginTime)) AS day, COUNT(DISTINCT userId) 
FROM UserSession 
WHERE loginTime BETWEEN :fromTime AND :toTime 
GROUP BY day 

Les FROM_DAYS/TO_DAYS convertira le loginTime à un certain nombre de jours, puis revenir à un datetime mais avec l'heure/minute/seconde parties zero'd.

Questions connexes