2014-11-26 43 views
12

Ich habe eine Abfrage, die wie folgt aussieht:Ist es möglich, eine Unterabfrage mit Sequelize.js zu machen?

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; 

Ist es möglich, dies mit Sequelize.js ORM zu schreiben? Ich weiß, ich kann einfach eine query direkt verwenden, aber ich frage mich, ob es möglich ist, zu konstruieren.

+1

Ich glaube nicht. Eager Laden kann die nächste Sache sein. [Hier ist ein Beispiel, in dem Sequelize eine Sub-Query durch eifriges Laden wegen eines künstlichen "Limits" erzeugt (https://github.com/sequelize/sequelize/issues/1719). – bishop

+1

Ich weiß nichts über 'Sequelize.js'. Ist es möglich, etwas wie "EssayStats t1 LINKS JOIN EssayStats t2 ON t1.EssayId = t2.EssayId UND t1.EssayDate axiac

Antwort

3

Ich glaube nicht, dass eine saubere Antwort auf Ihre Frage möglich ist. Siehe #1869:

Abfrage auf die Through Model/Join Tabelle ist derzeit leider nicht möglich.

die Titel Frage zu beantworten, Sequelize wird automatisch eine Unterabfrage (zB #1719) erzeugen, aber Sie können eine benutzerdefinierte Unterabfrage nicht. Ich habe keine verbindliche Referenz für ein Negativ.


Es ist wie Sie Ihren Tisch aussieht, ist so etwas wie dieses:

EssayStats 
    EssayId 
    EssayDate 
    WordCount 

Dann könnten Sie so etwas tun:

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'] 
}); 

Alles, was es läuft zwei SELECT-Abfragen tut, Nehmen Sie die MAX und MIN aus diesen Abfragen nach der Bestellung durch Ihre Variable von Interesse, und nehmen Sie dann Ihre Differenz. Das gibt Ihnen das, woran Sie interessiert sind: Der Unterschied der Wortzahl zwischen der neuesten Version und der ersten Version.

Der Trick hier ist, eine SELECT-Anweisung in einem Attributfeld einzukapseln.

Natürlich ist es chaotisch und wahrscheinlich nicht so viel besser als die Dose sequelize.query. Aber es beantwortet den Kern Ihrer Frage.

Eine bessere Lösung könnte sein, Ihre Daten etwas zu denormalisieren und "wordCountDelta" direkt in Ihrem Essay-Modell zu speichern. Dann könnten Sie eine afterCreatehook haben, um das Feld automatisch zu aktualisieren. Das wäre höchstwahrscheinlich auch die schnellste Lösung.

Ich antwortete auf etwas ähnliches here.

1

ein Beispiel für Unterabfrage

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} 
    }] 
}); 

ich hoffe, nützlich: D

+0

Hallo @Derit, hier möchte ich einige Alias-Namen für Modell A, Modell B Join-Ausgabe und wieder beitreten diese Ausgabe mit Modell C. Gibt es eine Möglichkeit, es zu tun. Bsp: wähle uid, col1, col2, col3 aus (wähle A.id als uid, col1, col2, col3 von A inner join B in A.id = B.mid, wo eine Bedingung), als 't' innerer Benutzer beitreten t.uid = u.id – DRK

Verwandte Themen