sql server 2005/2008 conditional join - tsql

Is there such thing like conditional join:
SELECT *
FROM TABLE1 A
IF (a=='TABLE2') THEN INNER JOIN TABLE2 B ON A.item_id=B.id
ELSE IF (a=='TABLE3') THEN INNER JOIN TABLE3 C ON A.item_id=C.id
While a is a field in TABLE1.
I like to use this in stored procedures without using dynamic sql (without writing query as string and EXEC(#query)).
EDIT: I can't write:
IF (a=='TABLE2) THEN queryA
ELSE IF (a=='TABLE3') THEN queryB
Because a is a field of TABLE1.

EDIT: Modified answer based on comment below:
You could try to get clever with some left joins. This will return more columns, so you'd probably want to be more discriminating than just SELECT *.
SELECT *
FROM TABLE1 A
LEFT JOIN TABLE2 B
ON A.item_id = B.id
AND A.a = 'TABLE2'
LEFT JOIN TABLE3 C
ON A.item_id = C.id
AND A.a = 'TABLE3'
WHERE (B.id IS NOT NULL AND A.a = 'TABLE2')
OR (C.id IS NOT NULL AND A.a = 'TABLE3')

Updated the query as requried:
SELECT * FROM
(
SELECT *
FROM TABLE1 A INNER JOIN TABLE2 B
ON A.a='TABLE2' --This will eleminate the table rows if the value of A.a is not 'TABLE2'
AND A.item_id=B.id) A,
(SELECT * FROM
INNER JOIN TABLE3 C
ON A.a='TABLE3' --This will eleminate the table rows if the value of A.a is not 'TABLE3'
AND A.item_id=C.id
) B
) a

Related

postgresql How to share cte among different tables in plain sql?

Say select id from some_expensive_query is the cte I want to share. Currently I write two sql in a transaction:
with t as (select id from some_expensive_query) select * from t1 join t on t.id =t1.id;
with t as (select id from some_expensive_query) select * from t2 join t on t.id =t2.id;
As you can see, the cte is executed twice but I want something like:
t = select id from some_expensive_query;
select * from t1 join t on t.id =t1.id;
select * from t2 join t on t.id =t2.id;
for portability, I don't want to use pgsql or functions, anyway to solve this?
Why don't you use union all ?
with t as (select id from some_expensive_query)
select * from t1 join t on t.id =t1.id
union all
select * from t2 join t on t.id =t2.id;

How do I join two tables with same column names keeping values from one the tables

I have these two tables:
Table1
-------
id|a|b|c|d|
1 |0|1|0|6|
and
Table2
-------
id|a|c|
1 |3|2|
How do I join these two tables keeping the values from table2 but also the columns from table1, so that the table would look like this afterwards:
TableJoined
-------
id|a|b|c|d|
1 |3|1|2|6|
Tried with
SELECT * FROM Table2 a JOIN Table1 b WHERE a.id = b.id;
hoping that the first table mentioned would be the overrider
Or I guess you could do:
SELECT b.id, a.a, b.b, a.c, b.d FROM Table2 a JOIN Table1 b WHERE a.id = b.id;
You can achieve that by qualifying the * with the table alias:
SELECT a.* FROM Table2 a JOIN Table1 b WHERE a.id = b.id;
But you should never use * in a SELECT list except in ad-hoc queries. (The exception is count(*) which is OK to use).

Postgres JOIN on timestamp fails

Trying to do a simple FULL OUTER JOIN on a timestamp and it is outputing the full cartesian product instead of matching identical dates. What is wrong here?
SQL Fiddle with example data
CREATE TABLE A (
id INT,
time TIMESTAMP
);
CREATE TABLE B (
id INT,
time TIMESTAMP
);
Query:
SELECT A.Id AS a_id, A.Time AS a_time, B.Id AS b_id, B.Time AS b_time
FROM A
FULL OUTER JOIN B ON A.Time = B.Time
-- This works:
-- SELECT A.id, A.time, B.id, B.time
-- FROM A
-- FULL OUTER JOIN B ON A.id = B.id
You are using the wrong parameters on TO_DATE() on your INSERTS easy to test if you do
SELECT * FROM A;
SELECT * FROM B;
Instead of
TO_DATE('01-01-2002', '%d-%m-%Y')
Should be:
TO_DATE('01-01-2002', '%DD-%MM-%Y')
SQL DEMO
In your sql fiddle all your inserted dates are the same because your date pattern is wrong. Try using TO_DATE('01-01-2002', 'DD-MM-YYYY') instead of TO_DATE('01-01-2002', '%d-%m-%y')

SQL Join 2 tables, return records where only 1 value exists and no other values

I am faced with an issue returning data records. I first wanted to find records where a certain value existed '0000' in a column doing a join for 2 tables. Below is my T-SQL;
SELECT ColumnA, ColumnB, ColumnC
FROM Table1, Table2
WHERE Table1.ColumnB. = Table2.ColumnB
and ColumnC='0000'
This returns the desired data records where '0000' exists at least once in all returned records.
The question I have is, how do I do the same, only returning Distinct records where '0000' is the only value that exists (one or many times) and no other value exists for the returned data records
Many thanks!
SELECT distinct ColumnA, ColumnB
FROM Table1, Table2
WHERE Table1.ColumnB = Table2.ColumnB
and ColumnC = '0000'
except
SELECT distinct ColumnA, ColumnB
FROM Table1, Table2
WHERE Table1.ColumnB = Table2.ColumnB
and ColumnC <> '0000'
if you want to use a join
guessing ColumnC is in Table2
SELECT distinct Table1.ColumnA, Table1.ColumnB, Table2.ColumnC
FROM Table1
JOIN Table2
on Table1.ColumnB = Table2.ColumnB
and Table2.ColumnC = '0000'
left join Table2 exclude
on Table1.ColumnB = exclude.ColumnB
and exclude.ColumnC <> '0000'
where exclude.ColumnB is null
this may be the best performer
SELECT distinct Table1.ColumnA, Table1.ColumnB, Table2.ColumnC
FROM Table1
JOIN Table2
on Table1.ColumnB = Table2.ColumnB
and Table2.ColumnC = '0000'
and not exists (select * from table2 exclude
where exclude.ColumnB = Table1.ColumnB
and exclude.ColumnC <> '0000')
Here's a solution using the ALL keyword
SELECT DISTINCT
columna,
columnb,
columnc
FROM table1 t1
INNER JOIN table2 t2
ON table1.columnb = table2.columnb
WHERE t2.columnc = '0000'
AND t2.columnc = ALL (SELECT columnc
FROM table2 t2Check
WHERE t2.columnb = t2Check.columb)
Here's a Example where I'm using only one table since the joins in your problem aren't actually important.

How to use "as" to set alias for joined tables in oracle 10

I wrote this, and it is wrong syntax, help me fix it, I want 'T' to be an alias of the result of the two inner joins.
select T.id
from table1
inner join table2 on table1.x = table2.y
inner join table3 on table3.z = table1.w as T;
You cannot use aliases to name the "entire" join, you can, however, put aliases on individual tables of the join:
select t1.id
from table1 t1
inner join table2 t2 on t1.x = t2.y
inner join table3 t3 on t3.z = t1.w
In the projection, you will have to use the alias of the table, which defines the id column you are going to select.
You can't directly name the result of a join. One option is to use a subquery:
select T.id
from (
select *
from table1
inner join table2 on table1.x = table2.y
inner join table3 on table3.z = table1.w
) T
Another option is subquery factoring:
with T as (
select *
from table1
inner join table2 on table1.x = table2.y
inner join table3 on table3.z = table1.w
)
select T.id
from T