2014-11-26 9 views
12

У меня есть запрос, который выглядит следующим образом:Можно ли выполнить подзапрос с помощью 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; 

Можно ли написать это с Sequelize.js ОРМ? Я знаю, что могу просто использовать query, но мне интересно, можно ли его построить.

+1

Я не думаю, что так. Желательная загрузка может быть самой близкой. [Вот пример, где Sequelize генерирует подзапрос с помощью загруженной загрузки из-за искусственного 'limit'] (https://github.com/sequelize/sequelize/issues/1719). – bishop

+1

Я ничего не знаю о 'Sequelize.js'. Можно ли составить что-то вроде 'EssayStats t1 LEFT JOIN EssayStats t2 ON t1.EssayId = t2.EssayId И t1.EssayDate axiac

ответ

3

Не думаю, что возможен чистый ответ на ваш вопрос. См. #1869:

Выполнение запроса на сквозной модели/объединении таблицы невозможно в настоящее время неудачно.

Чтобы ответить на этот вопрос в заголовке, Sequelize будет автоматически генерировать подзапрос (например, #1719), но вы не можете сделать пользовательский подзапрос. У меня нет авторитетной ссылки на негатив.


Похоже, ваш стол что-то вроде этого:

EssayStats 
    EssayId 
    EssayDate 
    WordCount 

Тогда вы могли бы сделать что-то вроде этого:

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

Все, что он делает это работает два SELECT для запросов, взяв MAX и MIN из этих запросов после заказа вашей переменной интереса, а затем принимая во внимание ваши различия. Это даст вам то, что вас интересует: разность слов между самой последней версией и первой версией.

Хитрость здесь заключается в инкапсуляции инструкции SELECT в поле атрибута.

Конечно, это грязно, как черт возьми, и, вероятно, не все это намного лучше, чем консервы sequelize.query. Но он отвечает на суть вашего вопроса.

Лучшим решением может быть денормализация ваших данных и хранение «wordCountDelta» непосредственно в вашей модели эссе. Тогда вы можете получить afterCreatehook для автоматического обновления поля. Это, скорее всего, будет самым быстрым решением.

Я ответил на что-то подобное here.

1

пример для подзапроса

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

я надеюсь, полезно: D

+0

Привет @Derit, здесь я хочу, чтобы какое-то имя псевдонима для модели A, Model B присоединилось к выводу и снова присоединилось к этому выводу с моделью C. Есть ли способ сделать это. Ex: выберите uid, col1, col2, col3 from (выберите A.id как uid, col1, col2, col3 из внутреннего соединения B в A.id = B.mid, где somecondition), поскольку 't' внутренне присоединяют пользователей как u к t.uid = u.id – DRK

Смежные вопросы