Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Join tables on columns of composite foreign / primary key in a query

Tags:

CREATE TABLE subscription (    magazine_id bigint,    user_id     bigint,    PRIMARY KEY (magazine_id, user_id) );  CREATE TABLE delivery (    magazine_id bigint,    user_id     bigint,    FOREIGN KEY (subscription) REFERENCES subscription (magazine_id, user_id) ); 

What is a good way to query for deliveries given a particular subscription? Is there a way to assign a column name to PRIMARY KEY (magazine_id, user_id) and the corresponding foreign key so that I can query like this:

SELECT * FROM subscription JOIN delivery ON (delivery.subscription_fk = delivery.subscription_pk); 

Note: I can write something like this:

SELECT * FROM subscription JOIN delivery ON (delivery.magazine_id = subscription.magazine_id               AND delivery.user_id = subscription.user_id); 

However, I am under the impression that there is a less verbose way to achieve this.

like image 319
samol Avatar asked Feb 14 '14 23:02

samol


People also ask

Can we join two tables with primary foreign key relation?

Yes, you can! The longer answer is yes, there are a few ways to combine two tables without a common column, including CROSS JOIN (Cartesian product) and UNION. The latter is technically not a join but can be handy for merging tables in SQL.

Can a column in composite primary key be foreign key?

Is it possible to use one of the attributes of a composite primary key as a foreign key? Yes, this is quite common and perfectly valid.

How do I join two tables with common column in SQL?

SQL JOIN. A JOIN clause is used to combine rows from two or more tables, based on a related column between them. Notice that the "CustomerID" column in the "Orders" table refers to the "CustomerID" in the "Customers" table. The relationship between the two tables above is the "CustomerID" column.


2 Answers

There is a NATURAL JOIN:

SELECT * FROM   subscription NATURAL JOIN delivery; 

Quoting the manual on SELECT:

NATURAL

NATURAL is shorthand for a USING list that mentions all columns in the two tables that have the same names.

It would work for your test setup, but it's not strictly doing what you ask for. The connection is based on all columns sharing the same name. Foreign keys are not considered. The cases where NATURAL JOIN is a good idea are few and far between.

Simplify code / less verbose

For starters, you could use table aliases and you don't need parentheses around the join conditions with ON (unlike with USING):

SELECT * FROM   subscription s JOIN   delivery     d ON d.magazine_id = s.magazine_id                      AND d.user_id = s.user_id; 

Since column names in the join conditions are identical, you can further simplify with USING:

SELECT * FROM   subscription s JOIN   delivery     d USING (magazine_id, user_id); 

There is no syntax variant making joins based on foreign key constraints automatically. You would have to query the system catalogs and build the SQL dynamically.

like image 148
Erwin Brandstetter Avatar answered Oct 18 '22 01:10

Erwin Brandstetter


Doesn't delivery has two columns representing the foreign key? Then it should work like with a non-composite primary key SELECT * FROM subscription JOIN delivery ON (delivery.magazine_id = subscription.magazine_id AND delivery.user_id = subscription.user_id).

like image 23
Smutje Avatar answered Oct 18 '22 01:10

Smutje