Remix.run Logo
zabzonk 2 hours ago

> doing JOINs with the USING clause

I'm ashamed to say that despite using SQL from the late 1980s, and as someone that likes reading manuals and text books, I'd never come across USING. Probably a bit late for me now to use it (or not) :-(

tkejser 43 minutes ago | parent | next [-]

I didn't really write USING in anger until around 10 years ago, and I have been around a long time too.

Not all databases support it. But once you start using it (pun) - a lot of naming conventions snap into place.

It has some funky semantics you should be aware of. Consider this:

``` CREATE TABLE foo (x INT);

CREATE TABLE bar (x INT);

SELECT * FROM foo JOIN bar USING (x);

```

There is only one `x` in the above `SELECT *` - the automatically disambiguated one. Which is typically want you want.

n4r9 an hour ago | parent | prev [-]

I've used SQL for around a decade and also never came across it. I'm maintaining SQL code with hundreds if not thousands of basic primary key joins and this could make those queries way more concise. Now I want to know the reasons for not using USING!

tkejser 35 minutes ago | parent [-]

There are reasons for not USING.

First, you need to be aware of the implicit disambiguration. When you join with USING, you are introducing a hidden column that represents both sides. This is typically what you want - but it can bite you.

Consider this PostgreSQL example:

``` CREATE TABLE foo (x INT); INSERT INTO foo VALUeS (1);

CREATE TABLE bar (x FLOAT); INSERT INTO bar VALUES (1);

SELECT pg_typeof(x) FROM foo JOIN bar USING (x); ```

The type of x is is double, - because x was implicitly upcast as we can see with EXPLAIN:

``` Merge Join (cost=338.29..931.54 rows=28815 width=4) Merge Cond: (bar.x = ((foo.x)::double precision)) -> Sort (cost=158.51..164.16 rows=2260 width=8) ```

Arguably, you should never be joining on keys of different types. It just bad design. But you don't always get that choice if someone else made the data model for you.

It also means that this actually works:

``` CREATE TABLE foo (x INT); INSERT INTO foo VALUeS (1);

CREATE TABLE bar (x INT); INSERT INTO bar VALUES (1);

CREATE TABLE baz (x INT); INSERT INTO baz VALUES (1);

SELECT * FROM foo JOIN bar USING (x) JOIN baz USING (x); ```

Which might not be what you expected :-)

If you are both the data modeller and the query writer - I have not been able to come up with a reason for not USING.

n4r9 29 minutes ago | parent [-]

Thanks for the reply. The use case I have in mind is joining onto an INT primary key using a foreign key column of another table. This alone would remove a massive amount of boilerplate code.