仅在主表上聚合GROUP BY,而不是在连接中完整连接的表

我有五个表USER_ATTRIBQUESTION_MAINREPLY_MAINCATEGORY_MAINQSTN_CATG相关如下:

 m.QUESTION_MAIN.belongsTo(m.USER_ATTRIB, { foreignKey: 'POSTER_I', targetKey: 'USER_I'}); m.QUESTION_MAIN.hasMany(m.REPLY_MAIN, { foreignKey: 'QSTN_I' }); m.QUESTION_MAIN.belongsToMany(m.CATEGORY_MAIN, { through: m.QSTN_CATG, foreignKey: 'QSTN_I' }); m.QUESTION_MAIN.hasMany(m.QSTN_CATG, { foreignKey: 'QSTN_I' }); 

我想在QUESTION_MAIN上运行查询来获取有关问题的详细信息。 其中一个细节是对问题的答复数量,可以通过查询

SELECT COUNT(REPLY_MAINs.QSTN_I) GROUP BY QSTN_I;

我想要运行的组合查询是:

 SELECT `QUESTION_MAIN`.* ,`USER_ATTRIB`.`USERATTRIB_ID` AS `USER_ATTRIB.USERATTRIB_ID` ,`USER_ATTRIB`.`USER_NAME` AS `USER_ATTRIB.USER_NAME` ,`QSTN_CATGs`.`QSTN_CATG_ID` AS `QSTN_CATGs.QSTN_CATG_ID`, ,`QSTN_CATGs`.`CATG_I` AS `QSTN_CATGs.QSTN_CATG_I` ,`REPLY_MAINs`.`REPLY_ID` AS `REPLY_MAINs.REPLY_ID` , COUNT(`REPLY_MAINs`.`QSTN_I`) AS `REPLY_MAINs.REPLY_COUNT` FROM ( SELECT `QUESTION_MAIN`.`QUESTION_ID` , ( 6371 * acos( cos( radians(13.0508629) ) * cos( radians( QSTN_LOC_LAT ) ) * cos( radians( QSTN_LOC_LONG ) - radians(77.6092108) ) + sin( radians(13.0508629) ) * sin( radians( QSTN_LOC_LAT ) ) ) ) AS `DISTANCE` FROM `QUESTION_MAIN` AS `QUESTION_MAIN` WHERE ( SELECT `QSTN_I` FROM `QSTN_CATG` AS `QSTN_CATG` WHERE (`QSTN_CATG`.`QSTN_I` = `QUESTION_MAIN`.`QUESTION_ID`) LIMIT 1 ) IS NOT NULL HAVING `DISTANCE` < 5 ORDER BY `QUESTION_MAIN`.`CREATED` DESC LIMIT 3 ) AS `QUESTION_MAIN` LEFT OUTER JOIN `USER_ATTRIB` AS `USER_ATTRIB` ON `QUESTION_MAIN`.`POSTER_I` = `USER_ATTRIB`.`USER_I` INNER JOIN `QSTN_CATG` AS `QSTN_CATGs` ON `QUESTION_MAIN`.`QUESTION_ID` = `QSTN_CATGs`.`QSTN_I` LEFT OUTER JOIN `REPLY_MAIN` AS `REPLY_MAINs` ON `QUESTION_MAIN`.`QUESTION_ID` = `REPLY_MAINs`.`QSTN_I` AND `REPLY_MAINs`.`REPLY_STATUS` = 200 GROUP BY `QUESTION_ID` ORDER BY `QUESTION_MAIN`.`CREATED` DESC; 

这是进行查询的Sequelize:

 QUESTION_MAIN.findAll({ attributes:['QUESTION_ID', 'POSTER_I', ['( 6371 * acos( ' + 'cos( radians('+qstnFeedRequest.qstnLocLat+') ) ' + '* cos( radians( QSTN_LOC_LAT ) ) ' + '* cos( radians( QSTN_LOC_LONG ) - radians('+ qstnFeedRequest.qstnLocLong+') ) ' + '+ sin( radians('+qstnFeedRequest.qstnLocLat+') ) ' + '* sin( radians( QSTN_LOC_LAT ) ) ) ' + ')', 'DISTANCE' ] ], include: [ { model: USER_ATTRIB, attributes:['USER_NAME'] }, { model: QSTN_CATG, attributes: [['CATG_I', 'QSTN_CATG_I']], where: qstnCatgWhereClause }, { model: REPLY_MAIN, attributes: [[sequelize.fn('COUNT', sequelize.col('REPLY_MAINs.QSTN_I')), 'REPLY_COUNT']], where: {REPLY_STATUS: 200}, required: false } ], having:{ 'DISTANCE' : {$lt: 5} }, where: whereClause, group: ['QUESTION_ID'], limit: qstnFeedRequest.limit }) 

问题是GROUP BY子句是在内部查询中应用的,而不是在整个连接中:

 SELECT `QUESTION_MAIN`.*, ... FROM ( SELECT `QUESTION_MAIN`.`QUESTION_ID`, ... HAVING `DISTANCE` < 5 GROUP BY `QUESTION_ID` -- This should go outside ORDER BY `QUESTION_MAIN`.`CREATED` DESC LIMIT 3 ) AS `QUESTION_MAIN` LEFT OUTER JOIN `USER_ATTRIB` ... ORDER BY `QUESTION_MAIN`.`CREATED` DESC; 

这是造成计数错误的聚合。 无论我尝试什么,我都无法从内部查询中获取GROUP BY子句。

我如何使整个连接而不是主表单独?

在浏览了一半网页之后,我终于find了解决办法。

如链接在注释中的线程所述,在连接之外进行1:M查询的限制是低效的。 所以,Sequelize会为1:1和1:M关系分别进行查询, 因为 separate: true属性在1:M表的include语句中设置。

即使在这之后,还有几个问题:

如果表的连接列未包含在属性中,则代码会中断。

Sequelize也在内部表中应用了外部子句。 为了防止这一点,我添加了包含声明的truthy。

这是我修改后的最终续集:

 QUESTION_MAIN.findAll({ attributes:['QUESTION_ID', 'POSTER_I', ['( 6371 * acos( ' + 'cos( radians('+qstnFeedRequest.qstnLocLat+') ) ' + '* cos( radians( QSTN_LOC_LAT ) ) ' + '* cos( radians( QSTN_LOC_LONG ) - radians('+ qstnFeedRequest.qstnLocLong+') ) ' + '+ sin( radians('+qstnFeedRequest.qstnLocLat+') ) ' + '* sin( radians( QSTN_LOC_LAT ) ) ) ' + ')', 'DISTANCE' ] ], include: [ { model: USER_ATTRIB, attributes:['USER_NAME'] }, { model: QSTN_CATG, attributes: [['CATG_I', 'QSTN_CATG_I']], where: qstnCatgWhereClause }, { model: REPLY_MAIN, //this is the 1:M table attributes: ['QSTN_I', [sequelize.fn('COUNT', sequelize.col('REPLY_MAIN.QSTN_I')), 'REPLY_COUNT']], //QSTN_I is the column joining QUESTION_MAIN and REPLY_MAIN. Not including this in the attributes throws an error where: {REPLY_STATUS: 200}, group: ['QSTN_I'], //grouping it in this query instead of the main query separate: true,//the culprit having: {'REPLY_COUNT': {$ne: null}}, //this is a dummy having clause which always returns true. This is added to stop the outer having clause being applied to the inner query required: false } ], having:{ 'DISTANCE' : {$lt: 5} }, where: whereClause, limit: qstnFeedRequest.limit }) 

希望这可以节省2天的时间