2017-10-18 10 views
0

J'ai un cas d'utilisation où j'ai besoin de demander Appointment enregistrements en fonction de leurs created_at ou leurs valeurs start_on. Il existe deux types de rendez-vous: « Estimation » et « GLA (allez voir) », représentée par un champ type avec les valeurs 0 et 1.MySQL/Rails - requête dynamiquement un champ de table basé sur un attribut de chaque enregistrement

Si la nomination est de type estimation, les besoins de la requête pour utiliser le champ start_on - et si le rendez-vous est un GLA, la requête doit utiliser le champ created_at car les GLA ne sont pas planifiés et n'ont pas de valeurs start_on.

En ce moment, je suis l'interrogation des données à l'aide d'un champ Rails pour filtrer les propriétés vers le bas qui ont eu leur dernier rendez-vous de et à une certaine date comme si (les spectacles suivants « de »):

scope :last_appointment_from, ->(date, type) { 
    query = joins(:appointments) 
    query = query.where('appointments.start_on = (
    SELECT MAX(appointments.start_on) 
    FROM appointments 
    WHERE appointments.property_id = properties.id)') 
    query = query.where('appointments.start_on >= ?', date) 
    query 
} 

Mais cela ne demande que la valeur start_on.

J'ai essayé de faire GREATEST (MAX (start_on), MAX (created_at)) - mais je ne sais pas comment savoir quel champ utiliser dans la partie where('events.start_on >= ?', date). Après avoir tapé cela, j'ai pensé à une autre solution possible: créer simplement un autre champ de base de données mis à jour avec la date correspondante sur un rappel d'enregistrement actif en fonction du type de Rendez-vous, appelé query_field ou quelque chose (et exécuter un script pour définir cette valeur pour tous les enregistrements existants) - et de cette façon, je peux juste interroger sur ce champ?

Toute idée/aide est grandement appréciée!

+0

passerez-vous le type à la portée comme vous l'avez dans la question ou voulez-vous une liste cohérente des deux types ensemble? –

+0

Je veux une liste composée de celle qui est la plus grande. Il renvoie donc les propriétés dont le rendez-vous maximum (peu importe le type) a une date de début supérieure à la date choisie dans le cas d'une estimation, ou une date créée supérieure à la date choisie dans le GLA – gregblass

Répondre

0

Étant donné que vous avez déjà un champ de type, il peut s'agir d'un cas d'utilisation pour STI, c'est-à-dire le même schéma SQL pour le modèle mais un comportement différent du côté ruby.

Notez que le champ "Type" peut déjà causer des problèmes avec des rails que vous n'avez pas pris en compte car ce champ est généralement réservé spécifiquement aux rails Single Table Inheritance STI.

Si vous utilisez STI, vous pouvez simplement écrire un accesseur qui extrait le bon champ de la base de données et le présente pour chaque modèle.

+0

I used 'self.inheritance_column =: _type_disabled' – gregblass

+0

Ceci est une bonne façon de procéder. – gregblass

+0

Soyez prudents, car les STI peuvent être difficiles. : P – engineerDave

0

Je pense que cette approche devrait fonctionner en supposant qu'aucune nomination devrait avoir un created_at avant son start_on moins qu'il ne soit GLA

scope :last_appointment_from, ->(date, type) { 
    query = joins(:appointments) 
    query = query.where('GREATEST(appointments.start_on, appointments.created_at) = (
    SELECT GREATEST(MAX(start_on), MAX(created_at)) 
    FROM appointments 
    WHERE appointments.property_id = properties.id)') 
    query = query.where('GREATEST(appointments.start_on, appointments.created_at) >= ?', date) 
    query 
} 
0

Je ne suis pas très bon avec Rails mais pour MySQL pur, vous pouvez utiliser un où comme ceci:

 
WHERE (
     (appointments.created_at > date 
      AND appointments.type = 1) 
     OR 
     (appointments.start_on > date 
      AND appointments.type = 0) 
    )