SQL JOIN two tables: inner join on one column and left join on another

491140363:
Tom Bennett

I have two tables:

t1: (name, dt, value1)
t2: (name, dt, valuu2)

I want to inner join on the column name and left join on the column dt. In other words:

SELECT *
FROM t1 INNER JOIN t2 on t1.name=t2.name
LEFT JOIN t2 on t1.dt=t2.dt

Semantically, I want the following as a correlated SQL query:

SELECT *
FROM t1 
LEFT JOIN (SELECT * FROM t2 WHERE t1.name=t2.name) AS t2_ on t1.date = t2_.date

But that is going to be very slow. What would be a good way to implement this?

---EDIT--

Here is a small example as requested:

create or replace table t1(name integer, date integer, value integer);
create or replace table t2(name integer, date integer, value integer);

INSERT into t1 values(1, 10, 100);
INSERT into t1 values(2, 10, 200);
INSERT into t1 values(3, 30, 300);
INSERT into t1 values(4, 40, 400);

INSERT into t2 values(1, 10, 100);
INSERT into t2 values(2, 20, 200);
INSERT into t2 values(3, 30, 300);


SELECT *
FROM t1 
LEFT JOIN (SELECT * FROM t2 WHERE t1.name=t2.name) AS t2_ on t1.date = t2_.date

RESULT:

enter image description here

John Bollinger

I want to inner join on the column name and left join on the column dt.

Join type is defined in terms of the whole join condition, so what you are asking for does not make sense unless you mean you want to join a table twice.

From your clarification, I think you mean that you want rows for all names that are present in both tables, for each name the columns of t1 and either (i) the row(s) of t2 for which the dates match, or (ii) nulls. You present a version with a correlated inline view, and apparently you are concerned with query performance.

You cannot have both inner and outer semantics with the same join, so you are going to need either a subquery or multiple joins, but it should be possible to do better than the query presented in the question. One possibility would be to perform the outer join, and filter out the unwanted rows based on a(n uncorrelated) suquery:

SELECT *
FROM t1
  LEFT JOIN t2
    on t1.name=t2.name and t1.dt=t2.dt
WHERE t1 in (select name from t2)

Another possibility would be to use an uncorrelated inline view to form the inner join, and then left-join to that:

SELECT *
FROM (
    SELECT DISTINCT t1.*
    FROM t1 JOIN t2 ON t1.name = t2.name
  ) t1_
  LEFT JOIN t2
    on t1_.name=t2.name and t1_.dt=t2.dt

The SELECT DISTINCT could be costly there, but that would be difficult to predict even with more information about the database.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related