I have the following query and I am getting a multi-part identifier could not be bound exception. I realize why and my next thought was to use a CROSS APPLY, which didn't work. What I really need to do is join that subquery to make sure I get the most recent entry for a particular column.
Unfortunately, I've run out of ideas... How do I accomplish this query?
SELECT t1.*
FROM dbo.Table1 t1 (nolock)
INNER JOIN
(
SELECT TOP 1 t2_s.c1, t2_s.c2, t2_s.c4
FROM dbo.Table2 t2_s
WHERE t2_s.c1 = t1.c1
ORDER BY t2_s.dateStamped DESC
) t2
on t2.c1 = t1.c1
INNER JOIN dbo.Table3 t3
on t3.c1 = t2.c2 and t3.c2 = 1
WHERE t1.c2 = 'xxx'
Assuming you are using SQL Server, then CROSS APPLY should do what you want:
SELECT t1.*
FROM dbo.Table1 t1 (nolock) CROSS APPLY
(SELECT TOP 1 t2_s.c1, t2_s.c2, t2_s.c4
FROM dbo.Table2 t2_s
WHERE t2_s.c1 = t1.c1
ORDER BY t2_s.dateStamped DESC
) t2 INNER JOIN
dbo.Table3 t3
on t3.c1 = t2.c2 and t3.c2 = 1
WHERE t1.c2 = 'xxx';
Related
I use next SQL-query in Oracle DB:
SELECT T1.*,
T3.*
FROM MyTable1 T1
INNER JOIN MyTable2 T2 ON T2.Id1 = T1.Id
LEFT JOIN MyTable3#dblink1 T3 ON T3.Id2 = T2.Id
This query is very simple and fast (about 1 min, T1 contain about 1 million rows, T3 more then 10 million rows). Now I want to use MyTable4 from dblink1 for filtering selected rows data. For it, I use subquery:
SELECT T1.*,
T3.*
FROM MyTable1 T1
INNER JOIN MyTable2 T2 ON T2.Id1 = T1.Id
LEFT JOIN (SELECT Sub_T1.*
FROM MyTable3#dblink1 Sub_T1
INNER JOIN MyTable4#dblink1 Sub_T2 ON Sub_T2.Id3 = Sub_T1.Id
WHERE
Sub_T2.MyColumn1 = 'required value') T3 ON T3.Id2 = T2.Id
But this query is too slow (more then 20min). If I rewrite this query to:
SELECT T1.*,
T3.*
FROM MyTable1 T1
INNER JOIN MyTable2 T2 ON T2.Id1 = T1.Id
LEFT JOIN MyTable3#dblink1 T3 ON T3.Id2 = T2.Id
LEFT JOIN MyTable4#dblink1 T4 ON T4.Id3 = T3.Id
WHERE
T4.MyColumn1 = 'required value'
Then my query work fast again, but I donn't like result (I want to see columns of T3 as null, if WHERE return false).
How to improve my second query, for speed up it?
Does phrasing the query with parentheses solve the problem?
SELECT T1.*,
T3.*
FROM MyTable1 T1 INNER JOIN
MyTable2 T2
ON T2.Id1 = T1.Id LEFT JOIN
(MyTable3#dblink1 T3 JOIN
MyTable4#dblink1 T4
ON T4.Id3 = T3.Id AND
T4.MyColumn1 = 'required value'
)
ON T3.Id2 = T2.Id;
Or, also:
SELECT T1.*,
T3.*
FROM MyTable1 T1 INNER JOIN
MyTable2 T2
ON T2.Id1 = T1.Id LEFT JOIN
MyTable3#dblink1 T3
ON T3.Id2 = T2.Id
EXISTS (SELECT 1 FROM MyTable4#dblink1 T4 WHERE T4.Id3 = T3.Id AND T4.MyColumn1 = 'required value'
)
I would like to make the following join, which is some sort of UNION ALL in SQL. How to do it? Preferably how to do it by selecting all columns form t1 and t2 and declaring matching keys? I would like to avoid specifying column names if it is possible.
Update. I put some values in columns to be more specific. This is what I want:
Join 1
Probably I got answers for this:
Join 2
Use a full outer join, like so:
select *
from table1 t1
full outer join table2 t2
on t1.c4 = t2.c1 and t1.c5 = t2.c2
While SQL Server supports full outer joins, MySQL does not. This query can be rewritten in that situation as follows:
select *
from table1 t1
left outer join table2 t2
on t1.c4 = t2.c1 and t1.c5 = t2.c2
union
select *
from table1 t1
right outer join table2 t2
on t1.c4 = t2.c1 and t1.c5 = t2.c2
Based on your updated requirements, the form of this join specified above can be used with slight modifications like so:
select null,null,null,t.* from table1 s
right outer join table2 t on s.c4 = t.c1 and s.c5 = t.c2
union
select s.*,null,null from table1 s
left outer join table2 t on s.c4 = t.c1 and s.c5 = t.c2
Note that you will still need to include the literal value null in your select clause, once for each column that needs to be defaulted to null.
Demo
Use a FULL OUTER JOIN
Assuming C4 and C5 in your output example are from t2...
SELECT t1.C1, t1.C2, t1.C3, t2.C3, t2.C4
FROM t1
FULL OUTER JOIN t2 ON t1.C4 = t2.C1 AND t1.C5 = t2.C2
I'm struggling to figure out how I can add a convenience data column to a join table to use for evaluation.
Sorry if the terminology is incorrect, I'm a bit of an SQL newbie.
For this query structure:
SELECT t1.id
FROM
table1 t1
INNER JOIN
table2 t2 ON t1.c2 = t2.c1
WHERE
t1.c5=5;
...I would like to add a column in the join table that is calculated using a function of a few of t1s columns. For example, the sum of t1.x, t1.y, t1.z in a variable called score that can then be referenced in the WHERE clause.
The reason behind wanting to do this is it will be referenced multiple times and will reduce verbosity and help readability.
I presume it will look something like:
SELECT t1.id
FROM
table1 t1
INNER JOIN
table2 t2 ON t1.c2 = t2.c1
-- function(t1.x, t1.y, t1.z) as score
WHERE
t1.c5=5;
--AND score ...
Using PostgreSQL 9.3
If the score is calculated from the t1 columns, then use a subquery on t1:
SELECT t1.id
FROM (select t1.*, function(t1.x, t1.y, t1.z) as score
from table1 t1
) t1 INNER JOIN
table2 t2
ON t1.c2 = t2.c1
WHERE t1.c5 = 5 AND
t1.score . . .
A good option would be to use the having clause.
Select t1.id, SUM(t1.x + t1.y + t1.z)
FROM table1 t1 inner join table2 t2 on t1.c2 = t2.c1
WHERE t1.c5 = 5
GROUP BY t1.id
Having SUM(t1.x + t1.y + t1.z) = ...
Or, you could do a sub-query in the from clause. The below code makes some assumptions on structure.
SELECT t1.id
FROM
(Select SUM(t1.x + t1.y + t1.z) as score, t1.c5, t1.c2, t1.id
FROM table1 t1
GROUP BY t1.id
) t1
INNER JOIN table2 t2 on t1.c2 = t2.c1
WHERE
t1.c5=5
And t1.score = ...
I am running following query..
Select T1.* from T1
LEFT JOIN T2 ON T1.C1 = T2.C1
LEFT JOIN T3 ON T2.C3 = T3.C3
ORDER BY Case When T1.C1 = 'ABC' THEN 'XYZ' END AS COMMENTS
Its giving me Syntax error near AS. Unable to figure out the error.
You don't need the AS alias when using case in an order by
Select T1.* from T1
LEFT JOIN T2 ON T1.C1 = T2.C1
LEFT JOIN T3 ON T2.C3 = T3.C3
ORDER BY Case When T1.C1 = 'ABC' THEN 'XYZ' END
It's because you are trying to assign an alias to the ORDER BY clause - this is not allowed and I'm not sure what you want to achieve here?
You either need:
Select T1.* from T1
LEFT JOIN T2 ON T1.C1 = T2.C1
LEFT JOIN T3 ON T2.C3 = T3.C3
ORDER BY Case When T1.C1 = 'ABC' THEN 'XYZ' END
Or, if you want that CASE value to be returned in the SELECT as well, then you need:
Select T1.*, Case When T1.C1 = 'ABC' THEN 'XYZ' END AS COMMENTS
from T1
LEFT JOIN T2 ON T1.C1 = T2.C1
LEFT JOIN T3 ON T2.C3 = T3.C3
ORDER BY Case When T1.C1 = 'ABC' THEN 'XYZ' END
Also, again not sure of intention here so it depends, but you may need an ELSE on that CASE...
e.g.
ORDER BY CASE WHEN T1.C1 = 'ABC' THEN 'XYZ' ELSE T1.C1 END
I have to do 'left' or 'inner' join operation between tables depends on input parameter in my stored procedure. I know how to do it very simply:
if flag = 0
begin
select t1.*, t2.* from t1
inner join t2 on t2.id=t1.id
end
else
begin
select t1.*, t2.* from t1
left join t2 on t2.id=t1.id
end
Is there any more solution ? Thank you
you can do it using only left join by doing something like this
select t1.*, t2.* from t1
left outer join t2 on t2.id=t1.id
WHERE flag = 1 OR t2.id IS NOT NULL
You didn't mention the language, so maybe something like this:
select t1.*, t2.* from t1
left join t2 on t2.id=t1.id
if flag = 0
begin
where t2.id is not null
end
select t1.*, t2.*
from t1
inner join t2 on t2.id = t1.id
where flag = 0
UNION
select t1.*, t2.*
from t1
left outer join t2 on t2.id = t1.id
where coalesce(flag, 1) <> 0;