question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

LIMIT of query placed in subquery when using include

See original GitHub issue

This is related to #6025

The situation

I have simplified the ‘issue’ to this: Say I have a Book, a Book has one or more authors. Authors have written one or more books. I want to do count and get all Books that are written by authors with the name ‘Scott’ in their name field.

The code

Book model:
var Book = sequelize.define('book', {
  title: Sequelize.STRING,
  description: Sequelize.TEXT
})

Author model:
var Author= sequelize.define('author', {
  name: Sequelize.STRING,
})

Associations:
Book.belongsToMany(Author, {as: 'authors', foreignKey: 'book_id', through: 'j_author_book'});
Author.belongsToMany(Book, {as: 'books', foreignKey: 'author_id', through: 'j_author_book'});

Query:
Book.findAndCountAll({
  limit: 15,
  include: [ {model: Author, as: 'authors', where: {name: {$like: '%' + 'Scott' + '%'}}, order: [ ['name', 'ASC'] ]}
})

What do you expect to happen?

I expect 2 queries: 1: A count (this works, it is not the point) 2: A select that gets me the first 15 results that apply to the ‘%Scott%’ LIKE in the include statement.

What is actually happening?

I get a COUNT that for example says ‘5’ while the actual get query gives me no results. I have tracked this down to how sequelize seems to generate a subquery and puts the LIMIT in that subquery instead of in the parent query. See below for the SQL it generates. This would mean it would effectively ‘look in the first 15 books and then apply the ‘Scott’ LIKE statement to those 15’ even though the database might have hundreds of books. I have simplified the query slightly.

I have also ran a few scenarios where I left out the LIMIT (it works then) but also where I left out the LIKE (it works then as well), but if both are present, wham, no result.

SELECT 
    `Book`.*
FROM 
    (
        SELECT 
            `Book`.*
        FROM 
            `books` AS `Book` 
        WHERE 
            (
                `Book`.`deleted_at` >= CURRENT_TIMESTAMP 
                OR `Book`.`deleted_at` IS NULL
            ) 
            AND (
                SELECT 
                    `j_author_book`.`author_id` 
                FROM 
                    `j_author_book` AS `j_author_book` 
                    INNER JOIN `authors` AS `Author` ON `j_author_book`.`author_id` = `Author`.`id` 
                WHERE 
                    (
                        `Book`.`id` = `j_author_book`.`book_id`
                    ) 
                LIMIT 
                    1
            ) IS NOT NULL 
        ORDER BY 
            `Book`.`title` asc 
        LIMIT 
            0, 15 # <---- THIS IS THE PROBLEM
    ) AS `Scenario` 
    INNER JOIN (
        `j_author_book` AS `authors.j_author_book` 
        INNER JOIN `authors` AS `authors` ON `authors`.`id` = `authors.j_author_book`.`author_id`
    ) ON `Book`.`id` = `authors.j_author_book`.`book_id` 
    AND (
        (
            `authors`.`deleted_at` >= CURRENT_TIMESTAMP 
            OR `authors`.`deleted_at` IS NULL
        ) 
        AND `authors`.`name` LIKE '%Scott%'
    ) 
ORDER BY 
    `Book`.`title` asc

Dialect: mysql (not tested with anything else) Database version: MySQL 5.6 Sequelize version: Most recent build on github: https://github.com/sequelize/sequelize/commit/cc4ee8b86f656f9706e1dbf3a5d5600333f8975b

Why I referenced the other issue at the top

The situation seems more or less the same and adding ‘duplicating: false’ to the include DOES fix it, because it will remove the subquery. That issue did not seem to actually lead to a fix for the problem though. My opinion is that sequelize is placing that LIMIT in the wrong place and using ‘duplicating: false’ to work around it does not seem like a solution to me. With all due respect of course. 😃

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:7
  • Comments:10 (2 by maintainers)

github_iconTop GitHub Comments

45reactions
Kumagor0commented, Aug 13, 2017

@suksin subQuery: false did the trick for me.

5reactions
mrdedcommented, Oct 31, 2017

I also noticed, that if you have two includes, both must have duplicating: false.

var Book = sequelize.define('book');
var Author = sequelize.define('author');
var Language = sequelize.define('language');

Book.belongsToMany(Author, { through: RefBookAuthor, as: 'authors' });
Book.belongsToMany(Language, { through: RefBookLanguage, as: 'languages' });

Following call will give an error:

Book.findAll({
  limit: 2,
  include: [
    {model: Author, duplicating: false},
    {model: Language}
  ]
}))

SequelizeDatabaseError: Unknown column ‘authors->RefBookAuthor.book_id’ in ‘field list’

Read more comments on GitHub >

github_iconTop Results From Across the Web

Limit MySQL subquery results inside a WHERE IN clause ...
In this blog post, we discussed how to perform a subquery which limits the amount of returned rows, inside a MySQL WHERE IN...
Read more >
Alternative to using LIMIT keyword in a SubQuery in MYSQL
Now I want to select 10 rows with a distinct value of c ode_ver & code_ver NOT LIKE '%DevBld%' sorted by date desc....
Read more >
Limit in WHERE-Clause subquery - Salesforce Stack Exchange
The short answer is: No, you can't use ORDER and LIMIT in semi-join subqueries: COUNT , FOR UPDATE , ORDER BY , and...
Read more >
5 Restrictions on Subqueries - MySQL :: Developer Zone
Chapter 5 Restrictions on Subqueries ... In general, you cannot modify a table and select from the same table in a subquery. For...
Read more >
Subquery Limitations - MariaDB Knowledge Base
Subqueries in the FROM clause cannot be correlated subqueries. They cannot be evaluated for each row of the outer query since they are...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found