I've been grappling with a problem for some time, checking thread after thread on S/O to no avail. I should mention I'm building a SQL query for use in Crystal Reports.
I am attempting to join two tables together that MAY be joined via a junction table - this can be done via UNIONs but the table then links to itself and it can become very messy accounting for all potential scenarios.
Let's say we have three tables: t1, t2 and t3.
I'm after a quick and reusable way to say "LEFT JOIN t1 & t2 directly OR LEFT JOIN via table3".
Here's a really basic knock-up of what I'm looking for:
SELECT t1.ID, t2.ID
FROM t AS t1
LEFT JOIN (
t AS t2 ON t1.ID = t2.parentID OR (
t AS t2 ON t1.ID = t3.ID1 AND t3.ID2 = t2.ID ))
Is this at all possible without ending up with two versions of t2?
I'm hoping there's a function out there I'm just unaware of.
EDIT: the direct t2 join is to a 'parentId' column on t2 and t1 & t2 are aliases of the same column.
Here's my desired output:
+-------+--------+--------+-------+-------------+
| t1.ID | t3.ID1 | t3.ID2 | t2.ID | t2.parentID |
+-------+--------+--------+-------+-------------+
| 001 | NULL | NULL | 004 | 001 |
| 002 | 002 | 003 | 003 | NULL |
| 003 | NULL | NULL | NULL | NULL |
+-------+--------+--------+-------+-------------+
This probably close to your request. But if t3.ID1 is on the same domain than t2.ID you can have problems
SELECT t1.ID, t2.ID
FROM t1
LEFT JOIN t3
ON t1.ID = t3.ID1
LEFT JOIN t2
ON t1.ID = t2.ID
OR t3.ID2 = t2.ID
So maybe you can include some validations
SELECT S.ID1, COALESCE(S.ID2, T2.ID)
FROM
( SELECT t1.ID as ID1, t2.ID as ID2
FROM t1
LEFT JOIN t2
ON t1.ID = t2.ID
-- This step look weird if t1.ID = t2.ID you just print same ID twice.
) as S
LEFT JOIN t3
ON S.ID1 = t3.ID1
AND S.ID2 IS NULL -- ONLY JOIN IF NOT MATCH ON FIRST QUERY
LEFT JOIN t2
ON t2.ID1 = t2.ID
Related
I am using SQL Server to solve the following problem.
I have 3 tables T1, T2, T3
T1:
ID Name Country
----------------------
1 PR IN
2 AR US
T2:
ID AGE
------------
1 32
2 36
3 40
T3:
ID T1_ID T2_ID Amount
--------------------------------
1 1 1 100
2 1 2 300
Required output
T1.Name T2.Age T3.Amount
---------------------------------
PR 32 100
PR 36 200
PR 40 0
My query is :
select
T1.name, T2.Age, T3.amount
from
T3
join
T1 on T1.id = T3.T1_ID --fixed a typo here
right join
T2 on T2.id = T3.T2_ID
where
T1.id = 1
My current output is:
T1.Name T2.Age T3.Amount
--------------------------------
PR 32 100
PR 36 200
I would really appreciate any help on this
start the FROM statement on T2 and T1 because you want all records for T2 and T1 as a Cartesian product, limited by WHERE
instead of joining T3 in the FROM, using a subselect for T3 allows you to use ISNULL:
SELECT T1.NAME,
T2.age,
ISNULL((SELECT amount
FROM T3
WHERE T1.id = T3.T1_id
AND T2.id = T3.T2_id), 0) AS Amount
FROM T2 CROSS JOIN
T1
WHERE T1.id = 1
I have two tables T1 and T2, both of them contain a column ID and value.
I need to join T1 and T2 into T3 by means of ID.
T3 should contain columns ID, T1Value, and T2Value.
The main requirement is, ID of T1 and T2 is possible not mapped
T1:
ID VALUE
-----------
1 hi
2 hello
T2:
ID VALUE
----------
2 kitty
3 dog
Then, T3 should be
ID T1VALUE T2VALUE
----------------------
1 hi
2 hello kitty
3 dog
Is it possible to achieve this without using pivot table, or temp table (ideally should be a single executable query)?
Thanks.
You can use FULL OUTER JOIN
SELECT ID = COALESCE(T1.ID, T2.ID),
T1VALUE = T1.VALUE,
T2VALUE = T2.VALUE
FROM T1
FULL OUTER JOIN T2
ON T1.ID = T2.ID
There are lots of example on FULL OUTER JOIN . just search for it
Another way is to use UNION ALL
SELECT T1.ID, T1VALUE = T1.VALUE, T2VALUE = NULL
FROM T1
UNION ALL
SELECT T2.ID, T1VALUE = NULL, T2VALUE = T2.VALUE
FROM T2
I have 2 tables T1 and T2.
T1:
ID | Name
----+-------
A | A1
A | C1
T2:
ID | Name
-----+------
A | A1
A | B1
I want to retrieve records that have same ID and Name with flag 1 and Same ID and Different Name with flag 0. However, while joining the table in SQL Server, I am getting the a cross join which is:
A | A1 | A1 | 1
A | A1 | B1 | 0
A | C1 | A1 | 0
A | C1 | B1 | 0
But I need the answer as:
A | A1 | A1 | 1
A | C1 | B1 | 0
The above result is giving me the same information about name mismatch but in limited no. of rows and no repetition.
Could somebody let me know how can do this in SQL Server?
Is this what you're after:
SELECT T1.ID, T1.Name Name1, T2.Name Name2, case T1.Name when T2.Name then 1 else 0 end Result
from T1
inner join T2 on T1.ID = T2.ID
where T1.Name = T2.Name
or (not exists (select 1 from T2 where T1.Name = Name and T1.ID = ID)
and not exists (select 1 from T1 where T2.Name = Name and T2.ID = ID))
Use a union to keep things simple:
select T1.ID, T1.Name Name1, T2.Name Name2, 1 flag
from T1
join T2 on T1.ID = T2.ID
and T1.Name = T2.Name
union all
select T1.ID, T1.Name, T2.Name, 0
from T1
join T2 on T1.ID = T2.ID
and T1.Name != T2.Name
Using a union is not the most efficient way, but it’s much easier to understand and unless you have millions of rows, it will still run very fast (and union all is quite a bit faster than union)
you can use ROW_NUMBER and FULL JOIN
DECLARE #T1 TABLE (ID VARCHAR(5), Name VARCHAR(5))
INSERT INTO #T1 VALUES ('A', 'A1')
INSERT INTO #T1 VALUES('A', 'C1')
DECLARE #T2 TABLE (ID VARCHAR(5), Name VARCHAR(5))
INSERT INTO #T2 VALUES ('A', 'A1')
INSERT INTO #T2 VALUES ('A', 'B1')
SELECT T1.ID, T1.Name, T2.Name, CASE WHEN T1.Name = T2.Name THEN 1 ELSE 0 END
FROM
( SELECT ROW_NUMBER()OVER(PARTITION BY ID ORDER BY Name) AS RN, * FROM #T1 ) T1
FULL JOIN
( SELECT ROW_NUMBER()OVER(PARTITION BY ID ORDER BY Name) AS RN, * FROM #T2 ) T2
ON T1.ID = T2.ID AND T1.RN = T2.RN
Result:
ID Name Name
----- ----- ----- -----------
A A1 A1 1
A C1 B1 0
I have an issue regarding conditional inner join. Kindly have a look at the following sqlfiddle.
http://sqlfiddle.com/#!4/6dc88
Here i'm trying to get all the same name. but if in case the id is 1 then also get the same name and the name which has id of 0. Your help will be appriciated. thanks. here is the example
Table1
Id | Name
1 | A
2 | B
3 | C
Table2
Id | Name
1 | a
2 | b
3 | c
0 | d
Here is what i expect
A | a
B | b
C | c
A | d
Edit: Sorry i forget to mention my query, here is what i have tried so far..
select t1.name, t2.name from table1 t1
inner join table2 t2 on
CASE
WHEN t1.id = t2.id_copy and t1.id = 1 THEN
0
else
t1.id
END = t2.id_copy
Thanks in advance.
Assuming you mean that if table2.id is 0 then it should match with table1.id = 1, then this should do the trick:
with table1 as (select 1 id, 'A' name from dual union all
select 2 id, 'B' name from dual union all
select 3 id, 'C' name from dual),
table2 as (select 1 id, 'a' name from dual union all
select 2 id, 'b' name from dual union all
select 3 id, 'c' name from dual union all
select 0 id, 'd' name from dual)
select t1.name, t2.name
from table1 t1
inner join table2 t2 on (t1.id = case when t2.id = 0 then 1 else t2.id end);
NAME NAME_1
---- ------
A a
B b
C c
A d
If there's more complicated logic around what decides how non-matching (t1.id = t2.id) rows in table2 match with table1, then you'll have to explain the logic.
Personally I would prefer to use something simpler, like:
select t1.name, t2.name from table1 t1
inner join table2 t2
on t1.id = t2.id_copy or (t1.id = 1 and t2.id_copy = 0)
Hi I'm trying to create a view from two different tables that has an additional column that is a sum of Table1.Price1 - Table2.Price2. The view without the additional column is:
Create View testview AS (
SELECT t1.ID,t1.Price1,t2.Price2 FROM
Table1 t1
LEFT JOIN
Table2 t2
ON
t1.ID = t2.ID
);
Any help would be much appreciated, thank you.
Below is a representation of what the view would look like:
ID | Table1.Price1 | Table2.Price2 | Total |
---------------------------------------
1 | 15.00 | 5.00 | 10.00 |
2 | 10.00 | 2.50 | 7.50 |
Try this:
Create View testview AS
(SELECT t1.ID,t1.Price1,t2.Price2, (t1.Price1 - t2.Price2) as difference
FROM Table1 t1
LEFT JOIN Table2 t2
ON t1.ID = t2.ID );
Just add your SUM column, like this:
Create View testview AS (
SELECT t1.ID,t1.Price1,t2.Price2, t1.Price1-t2.Price2 AS [SUM] FROM
Table1 t1
LEFT JOIN
Table2 t2
ON
t1.ID = t2.ID
);
You can just add two columns with the +,-,*,/ operators like in:
Create View testview AS (
SELECT t1.ID,t1.Price1,t2.Price2, t1.Price1+t2.Price2 as total FROM
Table1 t1
LEFT JOIN
Table2 t2 ON t1.ID = t2.ID
);
This will result in your desired table structure