Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to generate nested select statements #352

Open
parnic opened this issue Sep 6, 2022 · 3 comments · May be fixed by #357
Open

How to generate nested select statements #352

parnic opened this issue Sep 6, 2022 · 3 comments · May be fixed by #357

Comments

@parnic
Copy link

parnic commented Sep 6, 2022

Apologies if this is answered somewhere, I tried searching and couldn't find anything.

If I wanted to generate a nested select statement/select subquery similar to the following:

SELECT * FROM players WHERE team_id IN (SELECT id FROM teams WHERE season_id IN (SELECT id FROM seasons WHERE status='active'))

Is that possible with goqu? I've tried something like this for the nested bits:

seasonQuery := dialect.From(models.TableNames.Seasons).Select(models.SeasonColumns.ID).Where(goqu.C(models.SeasonColumns.Status).Eq(models.SeasonsStatusActive))
teamQuery := dialect.From(models.TableNames.Teams).Select(models.TeamColumns.ID).Where(goqu.C(models.TeamColumns.SeasonID).In(seasonQuery))

but using an SQLite dialect it ends up generating a query like:

SELECT `id` FROM `teams` WHERE (`season_id` IN ((SELECT `id` FROM `seasons` WHERE (`status` = 'active'))))

where the extra () in the IN breaks the select from seeing multiple IDs.

Is there a way to use one SelectDataset, or a derivative of it, in an In() like this?

@parnic
Copy link
Author

parnic commented Sep 6, 2022

It looks like replacing In() with Eq() in the code above causes goqu to turn the Eq into an In internally and generate an appropriate query, so that works for me. I wouldn't have expected it to do that translation (especially when In() doesn't work the same way), so I guess consider this a feature request instead of a question.

Behaves as desired:

seasonQuery := dialect.From(models.TableNames.Seasons).Select(models.SeasonColumns.ID).Where(goqu.C(models.SeasonColumns.Status).Eq(models.SeasonsStatusActive))
teamQuery := dialect.From(models.TableNames.Teams).Select(models.TeamColumns.ID).Where(goqu.C(models.TeamColumns.SeasonID).Eq(seasonQuery))

=>

SELECT `id` FROM `teams` WHERE (`season_id` IN (SELECT `id` FROM `seasons` WHERE (`status` = 'active')))

@nic11
Copy link
Contributor

nic11 commented Sep 12, 2022

Hey @parnic, I've also recently stumbled upon this bug. I'll make the PR with a fix soon :) In short, In considers a subquery to be a list and that causes extra braces to be appended

@nic11 nic11 linked a pull request Sep 22, 2022 that will close this issue
@nic11
Copy link
Contributor

nic11 commented Sep 22, 2022

@parnic I made a PR. But looks like replacing In with Eq gives the desired behavour. Not sure why is this like so and if it is a really the desired behaviour to treat In(Select(...)) like a 'in the array of one select', but looks very quirky

It even has this in tests:

expressionTestCase{val: ident.Eq(ae), sql: `("a" IN (SELECT "id" FROM "test2"))`},

PS. Noticed that you told the same thing about Eq/In just when I finished writing this comment :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants