gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-29 01:37:21 25 4
gpt4 key购买 nike

我有五个表 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 子句被应用于 inside 内部查询,而不是整个连接:

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 子句。

如何对整个连接进行分组而不是单独对主表进行分组?

最佳答案

翻了半天的网,终于找到了解决办法。

正如在 link is in the comment 的帖子中所说,在连接之外进行限制的 1:M 查询效率低下。因此,Sequelize 会针对 1:1 和 1:M 关系单独查询给定 separate: true属性在 1:M 表的 include 语句中设置。

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

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

Sequelize 也在内表上应用外层 having 子句。为了防止这种情况,我在包含中添加了一个真实的 having 语句。

这是我修改后的最终 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, //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 天的时间

关于mysql - Sequelize GROUP BY 仅在主表而不是连接中的完整连接表上聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37339708/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com