Is it possible to craft a query that adds values within two tables:
For example, say you have two tables
id value
-- -----
a 1
c 2
d 3
f 4
g 5
and
id value
-- -----
a 1
b 2
c 3
d 4
e 5
Then when you 'add' the two tables you would get the result where the id's match. So, a=1+1=2, and simply the same result where they don't. So the query would return:
id value
-- -----
a 2
b 2
c 5
d 7
e 5
f 4
g 5
maybe something like
select coalesce(t1.id, t2.id) as id, (coalesce(t1.value, 0) + coalesce(t2.value, 0)) as value
from table1 t1 full outer join table2 t2 on t1.id = t2.id
Use:
SELECT x.id,
SUM(x.value)
FROM (SELECT t.id,
t.value
FROM TABLE_1 t
UNION ALL
SELECT t2.id,
t2.value
FROM TABLE_2 t2) x
GROUP BY x.id
You could do it like this - but the other answers are probably swifter:
SELECT t1.id, t1.value + t2.value AS value
FROM t1 INNER JOIN t2 ON t1.id = t2.id
UNION
SELECT t1.id, t1.value
FROM t1
WHERE t1.id NOT IN (SELECT t2.id FROM t2)
UNION
SELECT t2.id, t2.value
FROM t2
WHERE t2.id NOT IN (SELECT t1.id FROM t1)
SELECT
COALESCE(t1.id, t2.id) AS id,
COALESCE(t1.value, 0) + COALESCE(t2.value, 0) AS value
FROM
t1
FULL OUTER JOIN
t2 ON t1.id = t2.id
OR
SELECT
foo.id,
COALESCE(t1.value, 0) + COALESCE(t2.value, 0) AS value
FROM
(
SELECT t1.id FROM t1
UNION
SELECT t2.id FROM t2
) foo
LEFT JOIN
t1 ON foo.id = t1.id
LEFT JOIN
t2 ON foo.id = t2.id
SELECT ISNULL(T1.Col1.T2.Col1) as ID, (ISNULL(T1.Col2,0) + ISNULL(T2.Col2,0)) as SumCols
FROM T1 OUTER JOIN T2 ON T1.Col1 = T2.Col2
No grouping or anything. It handles the following cases
if an id is in T1 but not in T2 you will get the value in T1 and vice versa. This handles bi-directional inclusion.
If an ID is in both you will get the sum
Related
How can I do something like select * from T1 inner join T2 on (T1.ID=T2.ID OR T1.ID2=T2.ID)
When I execute this code, it seems to fall in a infinity loop so I guess I'm wrong.
In other words, how can I match one of two columns from T1 to one column from T2
T1
ID ID2
1 10
2 20
T2
ID value
1 dummy10
20 dummy20
Result
ID ID2 value
1 10 dummy10
2 20 dummy20
Try to do like this:
select *
from T1, T2
where T1.ID = T2.ID or T1.ID2 = T2.ID
you can use 2 select statements with union, like this:
select
t1.ID,
t1.ID2,
t2.value
from Table1 as t1
inner join Table2 as t2 on t1.ID = t2.ID
UNION
select
t1.ID,
t1.ID2,
t2.value
from Table1 as t1
inner join Table2 as t2 on t1.ID2 = t2.ID
/* this will exclude values selected by other statement */
where t1.ID2 not in (select ID2 from Table1 inner join Table2 on Table1.ID = Table2.ID)
The only issue I can see with the code you provide is that you have not specified from which table you want the common column ID to be selected:
proc sql;
select
t1.*
,t2.value
from t1
inner join t2
on t1.id = t2.id or t1.id2 = t2.id;
quit;
Otherwise, your code should work. Perhaps the size of the data being joined is the problem?
I have two tables that I want to join.
The case is in table 1 the default value is 1 then in table 2 the default value is 0
Table 1 Table 2
-------- ---------
1 0
1232342 1232342
1241232 1231231
I want to join table 1 and table 2 with condition that if table 2 is 0 then it will be replaced to 1.
SELECT T1.ID
FROM TABLE1 T1, TABLE2 T2
WHERE T1.ID = REPLACE(CASE WHEN T2 = 0 THEN 1 ELSE T2.ID END, 'X', 'E')
with this statement it does not return the other id's that are not 0 or 1
expected output
Table 1
--------
1
1232342
Use a join with a CASE. replace() is for string values:
select t1.*
from table1 t1
join table2 t2 on t1.id = case when t2.id = 0 then 1 else t2.id end;
use case when and sub-query
select t1.* from table1 t1 join
(
select case when t2.id=0 then 1 else t2.id end as id from table2 t2
) as t3 on t1.id=t3.id
Try using case when :
SELECT *
FROM TABLE1 T1 inner join TABLE2 T2
on T1.ID = (CASE WHEN T2.ID =0 THEN 1 ELSE T2.ID END)
Switch to modern, explicit JOIN syntax. Skip the case expression, simply use AND/OR instead:
SELECT T1.ID
FROM TABLE1 T1
JOIN TABLE2 T2
ON T1.ID = T2.ID OR (T1.ID = 1 and T2.ID = 0)
Or use INTERSECT:
SELECT ID FROM TABLE1
INTERSECT
SELECT case when ID = 0 then 1 else id end from TABLE2
Edited
I'm not asking How to write good query but those 3 queries return same results.
Query 1
SELECT v1.id
FROM (
SELECT DISTINCT t1.id
FROM t1 LEFT JOIN t2 ON t1.id = t2.id
WHERE t2.id IS NULL
) v1 INNER JOIN (
SELECT DISTINCT t3.id
FROM t3 LEFT JOIN t4 ON t3.id = t4.id
WHERE t4.id IS NULL
) v2 ON v1.id = v2.id;
Query 2
SELECT DISTINCT t1.id
FROM (t1 LEFT JOIN t2 ON t1.id = t2.id)
INNER JOIN (t3 LEFT JOIN t4 ON t3.id = t4.id) ON t1.id = t3.id
WHERE t2.id IS NULL AND t4.id IS NULL;
Query 3
SELECT DISTINCT t1.id
FROM t1 LEFT JOIN t2 ON t1.id = t2.id
INNER JOIN t3 ON t1.id = t3.id LEFT JOIN t4 ON t3.id = t4.id
WHERE t2.id IS NULL AND t4.id IS NULL;
Queries are not hard coded by programmer but generate dynamically by user input.
For example when user inserts find id in t1 (but not in t2) and in t3 (but not in t4), his indention is Query 1. But currently my program generates Query 3 and it looks like OK. I'm wondering this query has a bug in some cases, so that should be changed like Query 2 or 1.
User input (shown above) is just example and converting user input to JOIN statement is difficult at last to me.
Thanks in advanced.
This is the original query:
SELECT v1.id
FROM (SELECT DISTINCT t1.id
FROM t1 LEFT JOIN t2 ON t1.id = t2.id
WHERE t2.id IS NULL
) v1 INNER JOIN
(SELECT DISTINCT t3.id
FROM t3 LEFT JOIN t4 ON t3.id = t4.id
WHERE t4.id IS NULL
) v2
ON v1.id = v2.id;
If I understand correctly, you want ids that are in t1 and t3, but not in t2 and t4.
I would express the second query as:
SELECT distinct t1.id
FROM t1 INNER JOIN
t3
on t1.id = t3.id LEFT JOIN
t2
on t1.id = t2.id LEFT JOIN
t4
on t1.id = t4.id
WHERE t2.id IS NULL AND t4.id IS NULL;
I read your original query as asking for "all ids in T1 which are in both T1 and T3 but not in T2 or T4". Is that correct? If so, my query would be:
SELECT DISTINCT t1.id
FROM t1
WHERE EXISTS (SELECT 1 FROM t3 WHERE t1.id = t3.id)
AND NOT EXISTS (SELECT 1 FROM t2 WHERE t1.id = t2.id)
AND NOT EXISTS (SELECT 1 FROM t4 WHERE t1.id = t4.id)
Not sure what the real objective is, nor which dbms is being targeted
-- oracle
SELECT id FROM ( SELECT id FROM t1 MINUS SELECT id FROM t2 ) a
INTERSECT
SELECT id FROM ( SELECT id FROM t3 MINUS SELECT id FROM t4 ) b
;
-- sql server
SELECT id FROM ( SELECT id FROM t1 EXCEPT SELECT id FROM t2 ) a
INTERSECT
SELECT id FROM ( SELECT id FROM t3 EXCEPT SELECT id FROM t4 ) b
;
SELECT c.id from (
SELECT t1.id
FROM t1 LEFT JOIN t2 ON t1.id = t2.id
WHERE t2.id IS NULL
UNION ALL
SELECT t3.id
FROM t3 LEFT JOIN t4 ON t3.id = t4.id
WHERE t4.id IS NULL
) c GROUP BY c.id HAVING count(*) >= 2
;
The next one is potentially quite efficient BUT has a caveat
-- conditions apply, assumes t2 and t4 cannot have ids not in t1 or t3 respectively
SELECT c.id from (
SELECT a.id from (
(SELECT ID FROM T1)
UNION ALL
(SELECT ID FROM T2)
) a GROUP BY a.id HAVING count(*) = 1
UNION ALL
SELECT b.id from (
(SELECT ID FROM T3)
UNION ALL
(SELECT ID FROM T4)
) b GROUP BY b.id HAVING count(*) = 1
) c GROUP BY c.id HAVING count(*) >= 2
;
Fiddles:
| Oracle
| SQL Server |
MySQL |
i have this tables:
Table1:
id Name
1 Example1
2 Example2
Table2:
id Date..............
1 5.2.2014........
1 6.2.2014.........
1 6.2.2014........
2 16.1.2014.......
2 17.1.2014.......
And I need take id and Name from table1 and join table1.id = table2.id and from table2 take only top 1 row...
Example:
id Name Date
1 Example1 5.2.2014
2 Example2 16.1.2014
It is possible?
You can use row_number() to filter out all but the latest row per id:
select *
from (
select row_number() over (partition by id order by Date desc) as rn
, *
from Table2
) as t2
join Table1 as t1
on t1.id = t2.id
where t2.rn = 1 -- Only latest row
Well, a simple attempt would be
SELECT t1.*,
(SELECT TOP 1 t2.Date FROM Table2 t2 WHERE t2.ID = t1.ID t2.Date) t2Date
FROM Table1 t1
If you were using SQL Server, you could use ROW_NUMBER
Something like
;WITH Vals AS (
SELECT t1.ID,
t1.Name,
t2.Date,
ROW_NUMBER() OVER(PARTITION BY t1.ID ORDER BY t2.Date) RowID
FROm Table1 t1 LEFT JOIN
Table2 t2 ON t1.ID
)
SELECT *
FROM Vals
WHERE RowID = 1
Select t1.id, t1.name , MIN(t2.date)
From table1 t1
Inner Join table2 t2
On t1.id=t2.id
Group By t1.id, t1.name
I have 2 tables
Table 1
ID Status
1 D
2 F
3 D
Table 2
SID ID Approve
1 1 N
2 1 Y
3 1 Y
4 2 Y
5 3 Y
Result:- Should be
Table 1 (ID, Status)
3, D
2,F
Should not display 1 (As one of child rows have N in the Approve Column)
I need a query to joins 2 tables on ID and finds records that don not have N in their Approve column. Does anyone have any clue how to implement this?
I tried
SELECT * FROM Table1 AS t1
INNER JOIN Table2 AS t2
ON t2.id = t1.id
WHERE t2.Approve != 'N'
Doesn’t work
SELECT *
FROM Table1 t1
WHERE NOT EXISTS(SELECT * FROM Table2 t2 WHERE t2.ID = t1.ID AND t2.Approve = 'N')
More efficient and possibly easier to read is the following:
SELECT * FROM Table1 AS t1
LEFT JOIN Table2 AS t2
ON t2.id = t1.id
group by t1.id HAVING sum(t2.approve='Y') = count(t1.id)
Please Try
SELECT distinct t1.*
FROM Table1 AS t1
INNER JOIN Table2 AS tyes
ON tyes.id = t1.id
AND tyes.approve ='Y'
LEFT OUTER JOIN Table2 as tno
ON tno.id = t1.id
AND tno.approve ='N'
where tno.sid is null
It will select any line which is explicitely approved and never disapproved
Select * from table1 where id not in (select id from table2 where approve = 'N')
ID 1 is still returned since there is also a record in table 2 where approve = 'Y' for ID 1.
If you want to exclude any ID where approve is 'N' for any SID then you'll have to work with subqueries; roughly:
SELECT t1.ID,T1.Status FROM Table1 AS t1 INNER JOIN Table2 AS t2 ON t2.id = t1.id
where t1.id NOT IN (select id from Table2 where approve = 'N' and id = t1.id)
regards,
Stijn