2014-11-26 23 views
12

Ho una domanda che sembra:È possibile eseguire una sottoquery con Sequelize.js?

select es.EssayId, (esmax.WordCount - esmin.WordCount) 
from (select es.EssayId, min(es.EssayDate) as mined, max(es.EssayDate) as maxed 
     from EssayStats es 
     group by es.EssayId 
    ) es join 
    EssayStats esmin 
    on es.EssayId = esmin.EssayId and es.mined = esmin.EssayDate join 
    EssayStats esmax 
    on es.EssayId = esmax.EssayId and es.maxed = esmax.EssayDate; 

E 'possibile scrivere questo con Sequelize.js ORM? So che posso usare direttamente uno query, ma mi chiedo se sia possibile costruire.

+1

Io non la penso così. Il caricamento avido potrebbe essere la cosa più vicina. [Ecco un esempio in cui Sequelize genera una sotto-query tramite caricamento ansioso, a causa di un 'limite' artificiale] (https://github.com/sequelize/sequelize/issues/1719). – bishop

+1

Non so nulla di 'Sequelize.js'. È possibile comporre qualcosa come 'EssayStats t1 LEFT JOIN EssayStats t2 ON t1.EssayId = t2.EssayId AND t1.EssayDate axiac

risposta

3

Non credo sia possibile una risposta pulita alla tua domanda. Vedere #1869:

La ricerca sul modello passante/tabella join non è attualmente possibile sfortunatamente.

Per rispondere alla domanda del titolo, Sequelize genererà automaticamente una sottoquery (ad esempio, #1719), ma non si può fare una sottoquery personalizzato. Non ho un riferimento autorevole per un negativo.


Sembra che il tavolo è qualcosa di simile:

EssayStats 
    EssayId 
    EssayDate 
    WordCount 

allora si potrebbe fare qualcosa di simile:

return EssayStat.findAll({ 
    attributes: [ 
     [sequelize.literal('((SELECT wordCount FROM "EssayStats" WHERE "EssayId" = "EssayStat"."EssayId" EssayStat BY "createdAt" DESC LIMIT 1) - (SELECT wordCount FROM "EssayStats" WHERE "EssayId" = "EssayStat"."EssayId" EssayStat BY "createdAt" ASC LIMIT 1))'), 'difference'], 
     'EssayId' 
    ], 
    group: ['EssayId'] 
}); 

Tutto ciò che si sta facendo è in esecuzione due query SELECT, prendendo il MAX e il MIN da quelle query dopo l'ordine dalla tua variabile di interesse, e poi prendendo la tua differenza. Questo ti darà quello che ti interessa: la differenza del conteggio delle parole tra la versione più recente e la prima versione.

Il trucco qui è incapsulare un'istruzione SELECT in un campo di attributo.

Naturalmente, è disordinato come diamine e probabilmente non è molto meglio di quello in scatola sequelize.query. Ma risponde al succo della tua domanda.

Una soluzione migliore potrebbe essere quella di denormalizzare alcuni dati e memorizzare "wordCountDelta" nel modello Essay direttamente. Quindi potresti avere un afterCreatehook per aggiornare automaticamente il campo. Probabilmente sarebbe anche la soluzione più veloce.

Ho risposto a qualcosa di simile here.

1

un esempio per sottoquery

ModelA.findAll({ 
    where: { 
     $or: [ 
      {'$B.someColumn$' : someCondition}, 
      {'$C.someOtherColumn$' : someOtherCondition} 
     ] 
    }, 
    include: [{ 
     model: ModelB, 
     required: false, //true or false for required 
     where:{id:$id} 

    }, { 
     model: ModelC, 
     required: false, //true or false for required 
     where:{id:$id} 
    }] 
}); 

spero utile: D

+0

Ciao @Derit, qui voglio un nome alias per l'output di join del modello A, del modello B e ancora unire quell'output con il modello C. C'è un modo per farlo. Es: seleziona uid, col1, col2, col3 da (seleziona A.id come uid, col1, col2, col3 da Un inner join B in A.id = B.mid dove somecondition) come 't' inner unisci gli utenti come tu t.uid = u.id – DRK

Problemi correlati