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

Join two tables across two different schemas ( One database) #1589

Open
mishitpatel opened this issue Jul 23, 2016 · 3 comments
Open

Join two tables across two different schemas ( One database) #1589

mishitpatel opened this issue Jul 23, 2016 · 3 comments

Comments

@mishitpatel
Copy link

Hello,
How can we implement table join across two different schemas but the same database.
Technically schemas are just logical separation of tables within the same database so while writing a SQL query all we need to is prefix them with schema name.
For example,

select * 
from user_schema.users as users
inner join account_schema.accounts  as accounts
on users.users.id = accounts.user_id

I could probably write below kenx.js. Does that look good ?

knex.from('user_schema.users as users').innerJoin('account_schema.accounts as accounts', 
'users.id', 'accounts.user_id')

But then i saw .withSchema option with knex.js What is the advantage of using that option instead of prefixing the table name with schema. How can I use .withSchema option to join join tables from two different schemas ?

Knex.js Documentation 
------------------------
.withSchema([schemaName]) 
Specifies the schema to be used as prefix of table name.

knex.withSchema('public').select('*').from('users')

Outputs:
select * from `public`.`users`
@denkomanceski
Copy link

any solution for this one?

@codinggirl
Copy link

The document says Identifier Syntax, ie, table name, column name, has no place for selecting schema, so if you are doing schemaName.tableName, query might be rendered wrong.

It suggested use .withSchema('schemaName') instead.

But I found .withSchema only work in one schema all over the builder block.

As so far, I have the following temporary sollutins:

  • Do not use .withSchema at all in speasure query, include schema name in table name string.
    This against the document.

  • Use sub-query with .withSchema

    {
        let rows = await knex.withSchema("sandbox1")
            .select('first_name', 'last_name', 'phone', 'site', "sites.name as sname")
            .from('users')
            .leftJoin(
                knex.withSchema('public')
                    .table('sites')
                    .select()
                    .as("sites"),
                "sites.id",
                "users.site")
        console.log(rows)
    }

This way need use .as in sub query.

  • Use .joinRaw()
    {
        let queryBuilder = knex.withSchema("sandbox1")
            .select('first_name', 'last_name', 'phone', 'site', "sites.name as sname")
            .from('users')
            .joinRaw("left join public.sites as sites ON sites.id = users.site", [])
        let sql = queryBuilder.toSQL().toNative()
        let rows = await queryBuilder

        console.log((sql))
        console.log(rows)
    }
  • Use .raw()
    {
        let { rows ,rowCount } = await knex
            .raw('SELECT users.first_name, users.last_name, users.phone, users.site, sites.name as sname FROM sandbox1.users, public.sites WHERE sites.id = users.site;');

        console.log(rows)
    }

This has less benifits to use knex.

  • Use other libarary or ORMs or drivers.

The final power.

@leopragi
Copy link

leopragi commented Oct 13, 2020

Adding one more detail to @codinggirl 's answer:

Using joinRaw() you can bind the parameters. Which generates query with an identical syntax all over the query.

    {
        const queryBuilder = knex.withSchema("sandbox1")
            .select('first_name', 'last_name', 'phone', 'site', "sites.name as sname")
            .from('users')
            .joinRaw("left join ?? ON ?? = ??", ["public.sites", "sites.id", "users.site"])
        const sql = queryBuilder.toString()
        console.log(sql)
    }

Note: Positional bindings ? are interpreted as values and ?? are interpreted as identifiers.

Output with bindings on PG:
select "first_name", "last_name", "phone", "site", "sites"."name" as "sname" from "sandbox1"."users" left join "public"."sites" ON "sites"."id" = "users"."site"

Output with bindings on MSSQL:
select [first_name], [last_name], [phone], [site], [sites].[name] as [sname] from [sandbox1].[users] left join [public].[sites] ON [sites].[id] = [users].[site]

Meanwhile, without binding, it would always generate:
select "first_name", "last_name", "phone", "site", "sites"."name" as "sname" from "sandbox1"."users" left join public.sites ON sites.id = users.site

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

No branches or pull requests

4 participants