#mysql #node.js #sequelize.js
#mysql #node.js #sequelize.js
Вопрос:
В моем проекте есть две модели.
- Заказы
- Продукты
- Заказ продуктов (через) (есть столбец количества)
Мне нужны 5 наиболее покупаемых продуктов, заказ на которые подтвержден за определенный период
OrderProducts.init({
order_id: DataTypes.INTEGER(4),
product_id: DataTypes.INTEGER(4),
qtd: DataTypes.INTEGER(4),
price: DataTypes.DECIMAL(15, 2),
})
Orders.init({
order_id: {
type: DataTypes.INTEGER(4),
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
client_id: DataTypes.INTEGER(4),
amount: DataTypes.DECIMAL(15,2),
status: {
type: DataTypes.ENUM([
'PENDING',
'CONFIRMED',
'PROGRESS',
'CANCELED',
]),
allowNull: false,
defaultValue: 'PENDING',
},
})
Products.init({
product_id: {
type: DataTypes.INTEGER(4),
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
title: DataTypes.STRING(256),
description: DataTypes.TEXT,
})
Orders.belongsToMany(Products, {foreignKey: 'order_id', through: OrderProducts, as: 'products'})
Products.belongsToMany(Orders, {foreignKey: 'product_id', through: OrderProducts})
Одним из решений было бы выполнить поиск по таблице…
Ответ №1:
Я предполагаю, что qtd
каким-то образом является полем «количество». Если нет, и у вас может быть только один продукт каждого типа для каждого заказа, попробуйте переключиться на COUNT()
функцию. Я также предполагаю, что у вас есть дата-время покупки в таблице заказов, которую вы, естественно, вызвали бы purchaseDate
.
const queryStartDate = moment().subtract(1, 'months').startOf('day');
const queryEndDate = moment().endOf('day');
Products.findAll({
offset: 0,
limit: 5,
attributes: ['product_id', 'title',
[sequelize.literal(`(
SELECT SUM(op.qty)
FROM OrderProducts AS op
INNER JOIN Orders o ON o.order_id = op.order_id
WHERE
op.product_id = Product.product_id
AND o.purchaseDate >= $startDate
AND o.purchaseDate <= $endDate
AND o.status = 'CONFIRMED'
)`, {
bind: {
startDate: queryStartDate,
endDate: queryEndDate,
},
}), 'summedQty']
],
order: [[sequelize.literal('summedQty'), 'DESC']]
});
// Note:
// - I'm assuming [OrderProducts] and [Orders] are the names of the actual SQL tables.
// - In contrast, the `Product.product_id` reference is to whatever Sequelize renders the Products table's alias as, in the SQL query. It'll be a reference to the parent of the sub-query. This may need tweaking but it should be good-to-go.
// - Were I you, I would put those statuses in a Look-up-Table. Enums are great in applications but strings/varchars are costly in databases.
// - I can't remember if the `Sequelize.literal()` function takes a `bind` attribute, like the `Sequelize.query()` function does. If not, you'll have to use string interpolation and format-out the dates.
Ссылки: