2011-10-28 4 views
2

Je tente de condenser plusieurs appels SQL en un seul, et je voulais savoir si ce qui suit était possible.Appel SQL pour renvoyer le nombre de jours du mois avec des éléments de plusieurs jours

Voici mes tables.

Organization 
    id 

Event 
    id, 
    startDate 
    endDate 

FavoriteOrgs 
    userId 
    orgId 

Pour chaque jour du mois, je souhaite retourner le nombre d'événements survenus ce jour-là. Pas trop difficile, jusqu'à ce que vous ajoutiez le fait que événements peuvent s'étendre sur 2 ou 3 jours.

Voici ce que j'ai jusqu'à présent, qui montre exactement le nombre d'événements par jour, mais il ne comprend que l'événement en compte pour le jour où il commence.

SELECT DAYOFMONTH(CAST(o.start_date AS DATE)) AS dayNum, COUNT(*) AS count 
    FROM favoriteOrgs f, event e, organization o 
    WHERE f.user_id =200372 
    AND e.profile_id = o.id AND e.profile_id = f.profile_id AND o.id = f.profile_id 
    AND e.last_date >= '$startDate' 
    AND e.start_date <= '$lastDate' 
    GROUP BY e.start_date 
+0

Pouvez-vous poster votre schéma? – hafichuk

+0

Je l'ai posté dans la question, mais le voici à nouveau: organization (id); event (id, startDate, endDate); favoriteOrgs (userId, orgId) –

+0

Ce n'est pas un schéma. Je ne sais pas ce que c'est. Dans votre client mysql, exécutez 'organisation DESC', etc. Voir http://dev.mysql.com/doc/refman/5.0/en/describe.html. – hafichuk

Répondre

3

Votre modèle de données ne modélise pas réellement toutes les entités de votre système. Une entité est les dates pour lesquelles vous êtes intéressé à rapporter des choses.

Vous devez ajouter une table à votre base de données (ou utiliser une table temporaire, une table en ligne ou tout ce qui est disponible avec MySQL). Le tableau est simplement toutes les dates pertinentes. Même une table qui remonte à 1900 et passe à 2100 sera plutôt petite.

La requête devient alors trivial:

CREATE TABLE Calendar (
    calendar_date DATE NOT NULL, 
    CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED 
) 

SELECT 
    C.calendar_date, 
    COUNT(*) AS count 
FROM 
    favoriteOrgs F 
INNER JOIN Event E ON 
    E.profile_id = F.profile_id AND 
    E.last_date >= '$startDate' AND 
    E.start_date <= '$lastDate' 
INNER JOIN Organization O ON 
    O.id = F.profile_id AND 
    O.id = E.profile_id 
WHERE 
    F.user_id = 200372 
GROUP BY 
    C.calendar_date 

Vous avez désormais un avantage que vous pouvez ajouter des activités supplémentaires des informations spécifiques aux dates du calendrier, comme une colonne « is_holiday », « economic_quarter » ou autre. N'oubliez pas de pré-remplir la table, qui est une simple boucle que vous devez exécuter une fois.

+0

Wow. Excellente réponse, merci. Pardonnez mon inexpérience ici, mais actuellement les colonnes 'startDate' et 'endDate' de la table 'opportunity' sont des horodatages - comme les opportunités ont des heures de début et de fin ainsi que des dates. Existe-t-il un moyen d'utiliser cette solution avec des horodatages? –

+0

Si vous voulez seulement le décomposer par jour, je ne pense pas que le code est différent. Je suis une personne de MS SQL cependant et ils ont un type de données timestamp timestamp, donc je ne suis pas sûr de la façon dont MySQL gère. Si vous voulez le décomposer par heure ou quelque chose, alors vous pouvez juste JOINDRE dans un ensemble de nombres générés de 1 à 24 et un seau basé sur ceux avec les dates. La clé est de considérer votre ensemble de compartiments comme un ensemble de données lui-même. –

Questions connexes