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.

Join with multiple subqueries does not work

See original GitHub issue

I have the following sample module configuration to setup Peewee:

from peewee import JOIN
from peewee import Model
from peewee import SqliteDatabase
from peewee import TextField

db = SqliteDatabase(f"tmp-sample.db")


class BaseModel(Model):
    class Meta:
        database = db


class Employee(BaseModel):
    code = TextField(null=True, index=True)

    @staticmethod
    def valids(*fields):
        return Employee.select(*fields).where(Employee.code.is_null(False))


class SalesDetails(BaseModel):
    seller_code = TextField(null=True, index=True)
    manager_code = TextField(null=True, index=True)

    @staticmethod
    def valids(*fields):
        seller = Employee.valids(Employee.code).alias("seller")
        manager = Employee.valids(Employee.code).alias("manager")

        return (
            SalesDetails.select(*fields)
            .join(seller, join_type=JOIN.INNER, on=(SalesDetails.seller_code == seller.c.code))
            .join(manager, join_type=JOIN.LEFT_OUTER, on=(SalesDetails.manager_code == manager.c.code))
        )


db.connect()

# CREATE AND POPULATE DB
if not db.table_exists(SalesDetails):
    db.create_tables([Employee, SalesDetails])
    Employee(code="A123456").save()
    SalesDetails(seller_code="A123456", manager_code="NON-EXIST").save()

try:
    # ASSERTION THAT FAILS
    for sd in SalesDetails.valids():
        assert sd.seller_code == "A123456"
        assert sd.manager_code is None
finally:
    db.close()

When I execute the code above, the assertions statements does not pass. Sample output result:

Screenshot 2019-06-10 13 55 20

The generated RAW SQL work properly, but the constructed object does not have the fields it should be.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:12 (6 by maintainers)

github_iconTop GitHub Comments

4reactions
willianantunescommented, Jun 10, 2019

As a fantastic workaround, I could make it work by doing the following steps:

  • Copy the Peewee generated RAW SQL
  • Paste it inside raw function (look the details here)

Result:

Screenshot 2019-06-10 11 00 27

0reactions
logannccommented, Jun 11, 2019

@willianantunes Just a note, in your minimal example, if I modify the query to include .dicts() and then print out the record, I get {'id': 1, 'seller_code': 'A123456', 'manager_code': 'NON-EXIST'}

And if you look at where you declare the record, it is, in fact, NON-EXIST.

Are you expecting sd.manager_code to be None because it should be the null side of the outer join from the query? That is not intended to be the case given what you’ve written.

If I wrote something like

        return (
            SalesDetails.select(SalesDetails.seller_code, SalesDetails.manager_code, seller.c.code.alias('scode'), manager.c.code.alias('mcode'))
            .join(
                seller,
                join_type=JOIN.INNER,
                on=(SalesDetails.seller_code == seller.c.code),
            )
            .join(
                manager,
                join_type=JOIN.LEFT_OUTER,
                on=(SalesDetails.manager_code == manager.c.code),
            )
        ).dicts()

Then I would generate

SELECT "t1"."seller_code", "t1"."manager_code", "seller"."code" AS "scode", "manager"."code" AS "mcode"
FROM "salesdetails" AS "t1" INNER JOIN (SELECT "t2"."code" FROM "employee" AS "t2" WHERE ("t2"."code" IS NOT ?)) AS "seller" ON ("t1"."seller_code" = "seller"."code") LEFT OUTER JOIN (SELECT "t2"."code" FROM "employee" AS "t2" WHERE ("t2"."code" IS NOT ?)) AS "manager" ON ("t1"."manager_code" = "manager"."code")

and receive the following object (which corresponds to the attributes on a peewee object if I wasn’t using a dict): {'seller_code': 'A123456', 'manager_code': 'NON-EXIST', 'scode': 'A123456', 'mcode': None}.

scode and mcode correspond to the records on the joined table. They aren’t included by default.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Multiple INNER JOIN subqueries sql - Stack Overflow
I want to extend the query so that I have a column showing if the student particpated in the class. If I run...
Read more >
Complex joins in multiple subqueries - DBA Stack Exchange
This just leaves products that are not sold at the stores indicated. ... You want the records where the product_id exists in the...
Read more >
Subqueries and JOINs - MariaDB Knowledge Base
Rewriting subqueries as JOINs, and using subqueries instead of JOINs. ... A subquery can quite often, but not in all cases, be rewritten...
Read more >
Combining Multiple Joins with Subqueries - DQ Courses
I need to understand what is situation do I have a INNER JOIN to select statement. And what are the steps to solved...
Read more >
Creating a subquery to retrieve data from more than one table
You can specify up to 16 subqueries within a single SQL statement, and you can specify subqueries within a subquery. Subqueries run from...
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