简体   繁体   中英

How to get max values of table with sequelize model.findAll()

I have a use case where have to store every change made to the Products table as a version of row that has changed. so my table consists of rows like below:

https://i.stack.imgur.com/zXJ8S.png

So, when we use model.findAll() it will return all the rows including the version of each row. That would be fine for history view. here is the question, how can we get the all latest versions of rows in the table without returning previous versions(older changes) of it?. I'm a little concerned that we can use sequelize max attribute to achieve this. But not sure how it can be used to achieve my use case. can anyone please let me know how to do this? Thanks

Before going to sequelize

There are several ways to go about it, although subquery is one of the ways you can do it.

I have demonstrated adding a subquery with max function in the where clause.

Let's first replicate it in simple mysql

mysql> create table product (productId VARCHAR(200), docversion integer, name VARCHAR(200), price integer, location VARCHAR(200));
Query OK, 0 rows affected (1.01 sec)

mysql> insert into product(productID, docversion, name, price, location) VALUES('PID123', 0, 'Chair', 25, 'USA');
Query OK, 1 row affected (0.07 sec)

mysql> insert into product(productID, docversion, name, price, location) VALUES('PID123', 1, 'Chair', 32, 'USA');
Query OK, 1 row affected (0.12 sec)

mysql> insert into product(productID, docversion, name, price, location) VALUES('PID456', 0, 'Table', 39, 'UK');
Query OK, 1 row affected (0.16 sec)

mysql> insert into product(productID, docversion, name, price, location) VALUES('PID456', 1, 'Table', 43, 'Canada');
Query OK, 1 row affected (0.08 sec)

mysql> insert into product(productID, docversion, name, price, location) VALUES('PID123', 2, 'Chair', 29, 'UK');
Query OK, 1 row affected (0.09 sec)

mysql> select * from product;
+-----------+------------+-------+-------+----------+
| productId | docversion | name  | price | location |
+-----------+------------+-------+-------+----------+
| PID123    |          0 | Chair |    25 | USA      |
| PID123    |          1 | Chair |    32 | USA      |
| PID456    |          0 | Table |    39 | UK       |
| PID456    |          1 | Table |    43 | Canada   |
| PID123    |          2 | Chair |    29 | UK       |
+-----------+------------+-------+-------+----------+
5 rows in set (0.00 sec)


mysql> select * from product where  location='USA' AND name='Chair' AND docversion = (select max(docversion) from product where location='USA' AND name='Chair' group by productId);
+-----------+------------+-------+-------+----------+
| productId | docversion | name  | price | location |
+-----------+------------+-------+-------+----------+
| PID123    |          1 | Chair |    32 | USA      |
+-----------+------------+-------+-------+----------+
1 row in set (0.01 sec)

Now converting the same query to sequelize

product.findAll({
  where: {
      location:{
          [Op.eq]: 'USA',
      },
      name:{
          [Op.eq]: 'Chair',
      },
      docversion:{
          [Op.eq]: sequelize.literal(`select max(docversion) from product where location='USA' AND name='Chair' group by productId`),
      },
  }
})

Here is what I think you can use for this problem. I add where condition too in case you need it with where condition.

Product.findAll({
  attributes: [
    "ProductId",
    "Name",
    "Price",
    "Location",
    [sequelize.fn("max", sequelize.col("max",sequelize.col("docVersion"), "latestDocVersion"],
  ],
  where: {
    Location: "USA"
  },
  raw: true
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM