I have two tables which I need to use a where clause.
Table1
CustomerID Product
1 Car
2 Table
3 Golf
4 Foo
5 Yoo
Table2
CustomeID Comment
2 Three items
3 Returned
4 Complaint
I have a query which has two filters in the where statement like this
Select * from table1 a left
join table2 b on a.customerid= b.customerid
where b.comment<>'Returned' and b.comment not like 'Three%'
When I ran the query I just got one record. I want it to also return the two customerID's which are not in table2(three records)
SELECT * FROM Table1 A
LEFT JOIN Table2 B
ON A.CustomerID=B.CustomeID
WHERE ( B.COMMENT<>'RETURNED' AND B.COMMENT NOT LIKE 'THREE%')
OR B.CustomeID IS NULL
This should work I guess.
Try:
SELECT *
FROM table1 a
LEFT JOIN table2 b on a.customerid= b.customerid
WHERE (b.comment<>'Returned' and b.comment not like 'Three%')
OR (b.customerid is NULL)
I think you need to use LEFT OUTER JOIN:
Select * from table1 a left outer join table2 b on a.customerid = b.customerid where b.comment<>'Returned' and b.comment not like 'Three%'
I usually tend not to JOIN that much.
SELECT --It's a good practice to enumerate all rows you need, not just *.
T1.CUSTOMERID,
T1.PRODUCT
FROM
TABLE1 T1
WHERE
T1.CUSTOMERID NOT IN (
SELECT
T2.CUSTOMERID
FROM
TABLE2 T2
WHERE
T2.COMMENT !='Returned' AND
T2.COMMENT not like 'Three%')
Related
I have a table t1. It has columns [id] and [id2].
Select count(*) from t1 where id=1;
returns 31,189 records
Select count(*) from t1 where id=2;
returns 31,173 records
I want to know the records where id2 is in id=1 but not in id=2.
So, I use the following:
Select * from t1 a left join t1 b on a.id2=b.id2
Where a.id=2 And b.id=1
And b.id2 Is Null;
It returns zero records.
Using an inner join to see how many records have id2 in common, I do...
Select * from t1 a inner join t1 b on a.id2=b.id2
Where a.id=2 And b.id=1;
And that returns 31,060. So where are the extra records in my first query that don't match?
I am sure I must be missing something obvious.
Sample Data
id id2
1 101
1 102
1 103
2 101
2 102
My expected results is to find the record with '103' in it. 'id2' not shared.
Thanks for any help.
Jeff
You are attempting to do what is generally called an exclude join. This involves doing a LEFT JOIN between two tables, then using a WHERE clause to only select rows where the right table is null, i.e. there was no record to join. In this way, you select everything from the left table except what exists in the right table.
With this data, it would look something like this:
SELECT
t1.id,
t1.id2
FROM test_table t1
LEFT JOIN
(SELECT
id,
id2
FROM test_table
WHERE id = 2) t2
ON t2.id2 = t1.id2
WHERE t1.id = 1
AND t2.id IS NULL --This is what makes the exclude join happen
And here is a SQLFiddle demonstrating this in MySQL 5.7 with the sample data you provided.
I think maybe Access changes the left join to an inner join when you add a where clause to filter rows (I know SQL Server does this), but if you do the filtering in derived tables it should work:
select
a.*
from
(select * from t1 where id = 1) a
left join
(select * from t1 where id = 2) b
on a.id2 = b.id2
where b.id2 is null
I have one table that I need to bump against multiple tables with left outer joins excluding the right(s). Is there a best practice for this? Union all the other tables first? Something else?
Here's the first thought that comes to my mind to handle this, but I want to know if there is a better more efficient way.
select
master_table.*
from
master_table
left outer join
(
select customer_id from table_1
union
select customer_id from table_2
union
select customer_id from table_3
union
select customer_id from table_4
) bump_table
on
master_table.customer_id = bump_table.customer_id
where
bump_table.customer_id is null
I should think a NOT EXISTS would be better. It certainly better communicates the intent of the query.
select * from master_table m
where not exists( select 1 from table_1 where m.customer_id=table_1.customer_id)
and not exists( select 1 from table_2 where m.customer_id=table_2.customer_id)
and not exists( select 1 from table_3 where m.customer_id=table_3.customer_id)
and not exists( select 1 from table_4 where m.customer_id=table_4.customer_id)
The basic form is surely faster - similar to the NOT EXISTS that #dbenham already supplied.
SELECT m.*
FROM master_table m
LEFT JOIN table_1 t1 ON t1.customer_id = m.customer_id
LEFT JOIN table_2 t2 ON t2.customer_id = m.customer_id
LEFT JOIN table_3 t3 ON t3.customer_id = m.customer_id
LEFT JOIN table_4 t4 ON t4.customer_id = m.customer_id
WHERE t1.customer_id IS NULL
AND t2.customer_id IS NULL
AND t3.customer_id IS NULL
AND t4.customer_id IS NULL;
How I can join this queries to single select (without temp table)?
SELECT t2.value,
t1.value
FROM table0 t1
INNER JOIN table1 t3 on t1.idrelation = t3.id and t3.idparent=#id
INNER JOIN table2 t2 on t2.idversion = t3.idchild and t2.name = 'FOO'
ORDER BY t1.value
SELECT SELECT COALESCE(t4._NAME+','+'')
FROM table1 t1
JOIN table1 t2 on t2.idparent = t1.idchild
JOIN table1 t3 on t3.idparent = t2.idchild
JOIN table3 t4 on t4._ID = t3.idchild
WHERE t1.idparent = #id
AND t4._TYPE ='TXT_CAT'
Something like this would help (once you can tell the columns on which you want to join):
select *
from
(
QUERY 1
) q1
join
(
QUERY 2
) q2
on q1.key1 = q2.key2
If you want to join them, there has to be common or uncommon ground.
Putting the 2 selects together is the easy part when you join the resultant sets, but unless you want all permutations of Ans1 and Ans2, then it is wise to determine some sort of where clause to allow it to be more effecient, and narrow it down for you.
If you give more table information, We could be able to adjust and give you something further, but that is the best we can do without taking arbitrary guesses as to what you are trying to accomplish here.
One thing i can part unto you:
Select A.name, B.id from (Select A.name, A.date from A) join (Select B.id, B.date from B) on A.date = B.date;
I have two tables, linked with an outer join. The relationship between the primary and secondary table is a 1 to [0..n]. The secondary table includes a timestamp column indicating when the record was added. I only want to retrieve the most recent record of the secondary table for each row in the primary. I have to use a group by on the primary table due to other tables also part of the SELECT. There's no way to use a 'having' clause though since this secondary table is not part of the group.
How can I do this without doing multiple queries?
For performance, try to touch the table least times
Option 1, OUTER APPLY
SELECT *
FROM
table1 a
OUTER APPY
(SELECT TOP 1 TimeStamp FROM table2 b
WHERE a.somekey = b.somekey ORDER BY TimeStamp DESC) x
Option 2, Aggregate
SELECT *
FROM
table1 a
LEFT JOIN
(SELECT MAX(TimeStamp) AS maxTs, somekey FROM table2
GROUP BY somekey) x ON a.somekey = x.somekey
Note: each table is mentioned once, no correlated subqueries
Something like:
SELECT a.id, b.*
FROM table1 a
INNER JOIN table2 b ON b.parentid = a.id
WHERE b.timestamp = (SELECT MAX(timestamp) FROM table2 c WHERE c.parentid = a.id)
Use LEFT JOIN instead of INNER JOIN if you want to show rows for IDs in table1 without any matches in table2.
select *
from table1 left outer join table2 a on
table1.id = a.table1_id
where
not exists (select 1 from table2 b where a.table1_id = b.table1_id and b.timestamp > a.timestamp)
The quickest way I know of is this:
SELECT
A.*,
B.SomeField
FROM
Table1 A
INNER JOIN (
SELECT
B1.A_ID,
B1.SomeField
FROM
Table2 B1
LEFT JOIN Table2 B2 ON (B1.A_ID=B2.A_ID) AND (B1.TimeStmp < B2.TimeStmp)
WHERE
B2.A_ID IS NULL
) B ON B.A_ID = A.ID
Is it possible to write a sql query where you know you have to use the left outer join..but cannot or are not allowed to use the "outer join" Key Word
I have two table sand want to get rows with null vaues from the left table ...this is pretty simple ...but am not supposed to use the key word....outer join....I need to right the logic for outer join myself
SELECT Field1
FROM table1
WHERE id NOT IN (SELECT id FROM table2)
SELECT Field1
FROM table1
WHERE NOT EXISTS (SELECT * FROM table2 where table2.id = table1.id)
This is something people do but it is deprecated and it does not currently work correctly (it sometimes will return a cross join instead of a left join) so it should NOT be used. I'm telling this only so you avoid using this solution.
SELECT Field1
FROM table1, table2 where table1.id *= table2.id
;WITH t1(c,d) AS
(
SELECT 1,'A' UNION ALL
SELECT 2,'B'
),t2(c,e) AS
(
SELECT 1,'C' UNION ALL
SELECT 1,'D' UNION ALL
SELECT 3,'E'
)
SELECT t1.c, t1.d, t2.c, t2.e
FROM t1, t2
WHERE t1.c = t2.c
UNION ALL
SELECT t1.c, t1.d, NULL, NULL
FROM t1
WHERE c NOT IN (SELECT c
FROM t2
WHERE c IS NOT NULL)
Returns
c d c e
----------- ---- ----------- ----
1 A 1 C
1 A 1 D
2 B NULL NULL
(Equivalent to)
SELECT t1.c, t1.d, t2.c, t2.e
FROM t1
LEFT JOIN t2
ON t1.c = t2.c
For SQL Server, you can just use LEFT JOIN - the OUTER is optional, just like INTO in an INSERT statement.
This is the same for all OUTER JOINs.
For an INNER JOIN you can just specify JOIN with no qualifiers and it is interpreted as an INNER JOIN.
This will give you all the rows in table A that don't have a matching row in table B:
SELECT *
FROM A
WHERE NOT EXISTS (
SELECT 1
FROM B
WHERE A.id = B.id
);
Returns all the matching rows from both tables:
SELECT a.*,b.* FROM table_a a, table_b b
WHERE a.key_field = b.key_field
Potential drawback is non-matches will be skipped.