I have 2 access tables that contain partially similar data, one being more enriched than the other.
The idea here is to join the two tables by the fields id and num and to get from the table T2 the num that are not in the table T1
T1:
id
num
1
34
3
51
7
23
T2:
id
num
status
1
34
done
1
79
done
1
39
done
3
51
done
7
23
done
Expected result:
id
num
status
1
79
done
1
39
done
Under access I read on internet that there is no MINUS operator like under MySQL, so I tried with EXCEPT but the query takes a long time (stopped after 10min)
So I tried this:
SELECT T2.*
FROM T2 LEFT JOIN T1 ON (T1.id =T2.id)
WHERE T1.num IS NULL AND ( (T2.status LIKE 'done') );
The problem now is, I don't have all the records that are in T2 but not in T1
You can use RIGHT JOIN. And I recommend to do not use "LIKE" in this case because this is slow. You can just use the = operator. So your query will be:
SELECT t2.id, t2.num, t2.status
FROM t1
RIGHT JOIN t2
ON t1.id = t2.id
AND t1.num = t2.num
WHERE t1.num IS NULL
AND t2.status = 'done';
In case all column names you want to join are identic in both tables, you can join more simple:
SELECT t2.id, t2.num, t2.status
FROM t1
RIGHT JOIN t2
USING (id,num)
WHERE t1.num IS NULL
AND t2.status = 'done';
I don't like this, but it's shorter. At the end, your concrete query depends on your personal "taste".
There is a lot of variants.
SELECT t2.*
FROM t2
LEFT JOIN t1 USING (id, num)
WHERE t1.id IS NULL
AND t2.status = 'done'
SELECT *
FROM t2
WHERE NOT EXISTS ( SELECT NULL
FROM t1
WHERE (t1.id, t1.num) = (t2.id, t2.num) )
AND status = 'done'
There are more variants...
What of these (or maybe some another) variants is the most effective? this depends on the tables definitions and data statistic.
You're missing a condition on the join:
SELECT T2.*
FROM T2
LEFT JOIN T1
ON T1.id = T2.id
AND T1.num = T2.num
WHERE T1.num IS NULL
AND T2.status LIKE 'done';
Check it here.
Related
I have two tables as such.
t1
id name
1 foo
2 bar
t2
tid id address
1 1 foss
I can execute select satement to select id 1 from t1 from both tables.
select * from t1 inner join t2 on (t1.id = 1 and t2.id = 1)
But, what I actually want is select bar from t1, and only bar, even though it isn't present in t2.
The above tables are similar to what I have been working on my project, and resembles to the same problem.
Here is what I tried.
1. I used left join t1.id = 2 and t2.id = 2
It lists all the values from t1, which I only wanted t1.id = 2.
2.inner join could be used, but since t2.id = 2 is not present.
Therefore, it doesn’t return anything.
But I wanted something that would display data from t1 and t2 if id is present in both tables, and if not display only from table t1 of only that id.
So, if I wanted to display t1.id = 2, the answer I would expect is using
select * from t1 join .....
id name tid id address
2 bar null null null
Based on your expected result this is a simple Left Join:
select *
from t1 left join t2
on t1.id = t2.id
where t1.id = 2
Use left join to get all elements of t1 even if a element of t2 with same id not exists.
Then use null to get only t1 when t2 not exists.
At last, you can add a where filter to get a subset of t1 (ie: id = 2)
SELECT t1.*, t2.*
FROM t1
LEFT JOIN t2
ON t1.id = t2.id
WHERE t2.id IS NULL
AND t1.id = 2;
How do I join these two tables together?
type count
NULL 117
2 1
type count
NULL 807
1 3
2 32
I've tried INNER JOIN, LEFT JOIN, and RIGHT JOIN and I can't quite figure it out. I would like the end result to look like
type count count
NULL 117 807
1 NULL 3
2 1 32
SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
Sourced from this question
You have a problem because NULLs do not match by default. But, you can make them match. Let me assume the first is t1 and the second t2
select t2.type, t1.count, t2.count
from t2 left join
t1
on t2.type = t1.type or (t2.type is null and t1.type is null);
Here is a SQL Fiddle that demonstrates that this correctly answers the OP's question.
The right type of join would be FULL OUTER JOIN, but it does not exist in MySQL.
We can emulate it in the following way:
SELECT t1.type, t1.count, t2.count # exact matches
FROM t1 join t2 on t1.type = t2.type
UNION
select t1.type, t1.count, NULL # t2 not present
FROM t1 left join t2 on t1.type = t2.type
WHERE t2.type IS NULL
UNION
select t2.type, NULL, t2.count # t1 not present
FROM t2 left join t1 on t2.type = t1.type
WHERE t1.type IS NULL
UNION
select NULL, t1.count, t2.count # NULL on both sides
FROM t1, t2
WHERE t1.type IS NULL and t2.type IS NULL;
I have a question for the question ;)
What would happen if the tables would look like follows? (just a small change)
type count
NULL 117
3 333
2 1
type count
NULL 807
1 3
2 32
Because in this case both tables contain records that do not match the other table, so probably joining from one direction is not enough and you need to join the tables from both directions, but then, you might have trouble using data for the 'type' from only one table...
So one solution might be something like:
select if (t1.type is null, t2.type, t1.type) as type, t1.count count1, t2.count count2
from t1
left join t2
on t1.type=t2.type or (t1.type is NULL and t2.type is NULL)
union
select if (t1.type is null, t2.type, t1.type) as type, t1.count count1, t2.count count2
from t1
right join t2
on t1.type=t2.type or (t1.type is NULL and t2.type is NULL);
In addition,
you may also use the coalesce() function instead of if (.. is null, ...) e.g. coalesce(t1.type, t2.type)
you may still need to be careful with union, perhaps you want to keep duplicated records (if there is any) and use union all
http://www.sqlfiddle.com/#!2/302e69/2
I have been using the following SQL:
SELECT DISTINCT NAME
FROM Events t1
LEFT JOIN UserHistory t2 ON t1.Name = t2.Event
WHERE t2.Event IS NULL
To select all rows from table 1 where table 2 is Null. This effectively filters out all my Table 1 data where Table 2 has data. However, I want to apply this only when a column in table 2 equals a certain value. Therefore I am looking to do a SELECT * FROM t2 WHERE t2.ID = 1 but am unsure how this fits into this query.
SELECT DISTINCT NAME
FROM Events t1
LEFT JOIN UserHistory t2 ON t1.Name = t2.Event and t2.certain_column = 1234
WHERE t2.Event IS NULL
Also you can try query with NOT EXISTS:
SELECT DISTINCT NAME
FROM Events t1
WHERE NOT EXISTS(SELECT * FROM UserHistory t2
WHERE t1.Name = t2.Event AND t2.ID = 1)
You need to add the predicate to the JOIN condition:
SELECT DISTINCT NAME
FROM Events t1
LEFT JOIN UserHistory t2 ON t1.Name = t2.Event AND t2.ID = 1
WHERE t2.Event IS NULL;
If you add it to the WHERE you effectively turn your outer join into an inner join, meaning no rows will be returned (since NULL = 1 evaluates to false)
Ok. I have some data in one table, that references on multiple occasions some data in another table.
Table1 - main client table
Table2 - user defined fields
Say I have a query that shows a client id from Table1 and all attached / used "used defined fields" from Table2
SELECT t1.Id, t2.udf
FROM Table1 t1
JOIN Table2 t2 ON t1.Id = t2.Index
WHERE t1.EndDate IS NULL AND
t1.Id = '1234.9876' AND
I would get the following for a result...
ID UDF
1234.9876 100
1234.9876 110
1234.9876 118
1234.9876 124
1234.9876 198
1234.9876 256
Now, say I wanted to query this same thing, and get ONLY the ID of the Client, but ONLY IF a value for t2.udf equaling '194' did not exist. So, I would simply get
ID
1234.9876
...as a result.
Make the join a LEFT join and filer where t2.Index is null
SELECT t1.Id
FROM Table1 t1
LEFT JOIN Table2 t2 ON t1.Id = t2.Index
AND t2.UDF = 194 -- has to be before where clause
WHERE t2.Index IS NULL
AND t1.EndDate IS NULL
AND t1.Id = '1234.9876' -- not sure if you want this part
Another way by using NOT EXISTS
SELECT t1.Id
FROM Table1 t1
WHERE NOT EXISTS (SELECT 1 FROM Table2 t2 WHERE t1.Id = t2.INDEX
AND t2.UDF = 194)
AND t1.EndDate IS NULL
AND t1.Id = '1234.9876'
See also JOINS
You can add AND t2.udf not in (select udf from table2 where udf <> '194').
But #SQLMenace solution is better
This should do it.
SELECT DISTINCT t1.Id
FROM Table1 t1
LEFT JOIN Table2 t2 ON t1.Id = t2.Index
WHERE t2.UDF NOT IN (194)
AND t2.Index IS NULL
Select DISTINCT gives you unique entries that satisfy the other conditions, and the first where clause
t2.UDF NOT IN (194)
Normall would return all the rows for the t1 where the t2.UDF is not 194, but it is limited by the Select Distinct to give you only distinct id's
Try the following:
SELECT t1.Id
FROM Table1 t1
JOIN Table2 t2 ON t1.Id = t2.Index
WHERE t1.EndDate IS NULL AND
t1.Id = '1234.9876' AND
t2.udf <> '194'
I have the 2 following tables t1, t2 with values,
t1 t2
1 4
2 2
3 3
Now I want to output
1
4
How can I get this output in select query ?
This will get you each item from t1 that is not present in t2, and each item in t2 that is not present in t1:
select t1.id from t1
left join t2 on t2.id = t1.id
where t2.id is null
union all
select t2.id from t2
left join t1 on t1.id = t2.id
where t1.id is null
(I have assumed that the field name in each table is named id just for the sake of being able to write a query against the tables.)
Another way would be:
select coalesce(t1.id, t2.id)
from t1
full outer join t2 on t2.id = t1.id
where t1.id is null or t2.id is null
Another way. Just COUNT them.
This works if the values are unique per table
SELECT
CombinedValue
FROM
(
SELECT t1 AS CombinedValue FROM t1
UNION ALL
SELECT t2 FROM t2
) foo
GROUP BY
CombinedValue
HAVING
COUNT(*) = 1
If not unique per table
SELECT
CombinedValue
FROM
(
SELECT DISTINCT t1 AS CombinedValue FROM t1
UNION ALL
SELECT DISTINCT t2 FROM t2
) foo
GROUP BY
CombinedValue
HAVING
COUNT(*) = 1
you can use Joins in MySql to proceed and to obtain result.
this will help you
http://www.techrepublic.com/article/sql-basics-query-multiple-tables/1050307