SQL query join question - sql

How do you do SQL query for the following condition? Suppose you have two tables: table1 and table2, where each entry in table1 can have multiple corresponding entries in table2. The pseudo code for the query that I want is:
for each $row in table1
$rows = find all rows in table2 that corresponds to $row with $row.id == table2.foreign_id
# $rows is an array of corresponding row in table2
if all rows in $rows meet some condition
then
return $row
else
continue
end
end
EDIT: note in the above pseudo code, I only want the row in table1 that has all its relations in TABLE2 that meets some conditions, not just some condition in table1.
PS: I want to do it in SQL due to efficiency problems that I may have otherwise.
Thanks a lot.

You can reformulate this with a where not exists ( .. ) type clause.
For example, pretending you want a list of customers whose orders are all completed:
select * from customers c
where not exists (
select * from orders
where customerid=c.id
and status <> 'C'
)
So you are asking for all customers who have no uncompleted orders - which is the same thing as all customers whose orders are all completed.
Instead of:
if all rows in $rows meet some condition
You are saying:
if NO rows in $rows DO NOT meet some condition
Edit: As pointed out in the comments, this will also return customers who have no orders. You could add and exists (select * from orders where customerid=c.id) to the end of the above to exclude these rows.

select * from table1 as t1
inner join table2 as t2
on t1.id == t2.foreign_id
where -- some condition goes here
This query will only return the rows from table1 that have a match in table2 and that match the where clause.
I would suggest checking out SQLCourse - Interactive Online SQL Training for Beginners since this really is a basic SQL query.

As ck mentioned, this is really basic sql.
for each $row in table1
SELECT table1.* FROM table1
find all rows in table2 that corresponds to $row with $row.id == table2.foreign_id
LEFT JOIN table2 ON table1.id = table2.foreign_id
if all rows in $rows meet some condition
WHERE condition_here
The entire SQL becomes
SELECT
table1.*
FROM table1
LEFT JOIN table2 ON table1.id = table2.foreign_id
WHERE condition_here

I think this is what you are getting at... The nested select is a derived table named sub_query and corresponds to this part of you pseudo code ($rows = find all rows in table2 that corresponds to $row with $row.id == table2.foreign_id). The outer select lets you further filter the first part of your pseudo code by some condition (your if statement)
select
sub_query.*
from
(select
*
from
table1,
table2
where
table1.id = table2.foreign_key_id) sub_query
where
sub_query.some_field = "some condition"
Enjoy!

Here's a possible solution. I use Oracle, not sure if the syntax is exactly right for MySQL, but I imagine you can work up an equivalent.
The idea of this is to find all ids in table2 for which all rows meet the desired condition, then look up those ids in table1.
SELECT *
FROM table1
WHERE id IN (
SELECT id
FROM table2
GROUP BY id
HAVING COUNT(*) = SUM( CASE WHEN <somecondition> THEN 1 ELSE 0 END )
)

general format is:
SELECT *
FROM Table1 t1
INNER JOIN Table2 t2 ON (t1.ID = t2.ID)
WHERE ...

Related

DELETE duplicates with subquery from 2 tables in MS Access

I have two tables with same structure that can have duplicated records, I want to identify which ones from table 2 already exists in table 1 and delete them from table 2. The following SELECT returns the duplicated records I want to delete. None of these tables have a primary key, so I need to do multiple 'ON' to identify unique records.
SELECT V.*
FROM table2 AS V
INNER JOIN table1 AS N
ON V.column1 = N.column1 AND V.column2 = N.column2 AND V.column3= N.column3;
Then I insert this as a subquery for the DELETE:
DELETE FROM table2
WHERE table2.column1 IN
(SELECT V.*
FROM table2 AS V
INNER JOIN table1 AS N
ON V.column1 = N.column1 AND V.column2 = N.column2 AND V.column3= N.column3);
When running this query I get the following error:
You have written a query that can return more than one field without using the reserved word EXISTS in the FROM clause of the main query. Correct the SELECT instruction of the subquery to request a single field.
I also tried this way, but it deletes all the records from table 2, not only the result of the subquery:
DELETE FROM table2
WHERE EXISTS
(SELECT V.*
FROM table2 AS V
INNER JOIN table1 AS N
ON V.column1 = N.column1 AND V.column2 = N.column2 AND V.column3= N.column3);
This is the first solution I came up with, but I'm wondering if it wouldn't be easier to do in MS Access inserting into table1 all the records from table2 that doesn't match, and then delete table2.
All sugestions will be appreciated :)
Take the advice of the error message and try using exists logic:
DELETE
FROM table2 t2
WHERE EXISTS (SELECT 1 FROM table1 t1
WHERE t1.column1 = t2.column1 AND
t1.column2 = t2.column2 AND
t1.column3 = t2.column3);
The problem with your current exists attempt is that the query inside the EXISTS clause always has a result set, and that result set is independent of the outer delete call. So, all records get deleted.
I think you're just missing the specific column in your subquery.
This should work better :
DELETE FROM table2
WHERE table2.column1 IN
(SELECT V.column1
FROM table2 AS V
INNER JOIN table1 AS N
ON V.column1 = N.column1 AND V.column2 = N.column2 AND V.column3= N.column3);

SQL IN operator value of subquery

I want to get a value from an IN subquery with two columns, without needing to do two queries.
Sample:
SELECT * FROM table1 WHERE id IN(SELECT id, flags FROM table2);
Now I want to get flags directly. Is it possible, and if yes, how?
Any help is appreciated :)
It sounds like you are trying to achieve one of two things:
1) Select every field of records in table1 (and the associated table 2 flag) where the record's id is also found in the id column of table2. If that is the case, then yes, a join will accomplish what you want:
SELECT t1.*,
t2.flags
FROM table1 t1
JOIN table2 t2
ON t1.id = t2.id;
Note that JOIN is used here (rather than other types of joins such as LEFT JOIN) because JOIN will return only table1 records with a match in table2.id. LEFT JOIN, on the other hand, would return every table1 record, and table1 ids without a match in table2 would simply have null in the flags column of your returned table.
2) Select every field of records in table1 where the record's id is also found in either the id column of table2 or the flags column of table2. If that is the case, there are a few ways you could get the desired result, but achieving this using a subquery similar to the question
SELECT *
FROM table1
WHERE id IN (SELECT id FROM table2 UNION DISTINCT SELECT flags FROM table2)
You do this using join:
SELECT t1.*, t2.flags
FROM table1 t1 JOIN
table2 t2
ON t1.id = t2.id;

How to extract non-duplicate values in two tables

I have two tables where each one contains columns with numbers. I need to compare columns in both tables and extract the number that does exist in first table, and does not exist in second one. I don't need unique value.
I wrote this query:
SELECT Table1.Numbers, Table1.Name
FROM Table1, Table2
WHERE Table1.Numbers != Table2.numbers
Since I am working on several million records can someone recommend more efficient query which would provide me with identical results?
I would use NOT EXISTS:
SELECT Table1.Numbers, Table1.Name
FROM Table1
WHERE NOT EXISTS(
SELECT 1 FROM Table2
WHERE Table1.Numbers=Table2.Numbers
)
Other approaches:
Should I use NOT IN, OUTER APPLY, LEFT OUTER JOIN, EXCEPT, or NOT EXISTS?
You can do this easily by checking for the existance on the number in Table2.
SELECT T1.Numbers
,T1.Name
FROM Table1 T1
WHERE NOT EXISTS (SELECT 1 FROM Table2 T2 WHERE T2.Numbers = T1.Numbers)
Try this (assuming that your Numbers column are not nullable)
SELECT T1.Numbers, T1.Name
FROM Table1 AS T1
LEFT JOIN Table2 AS T2 ON T1.Numbers = T2.Numbers
WHERE T2.Numbers IS NULL;
SELECT
Table1.Numbers, Table1.Name
FROM
Table1, Table2
GROUP BY
Table1, Table2
HAVING
COUNT(*) > 1

Pretty simple SQL query using another query

I need to select all IDs from one table with columns ID and X, WHERE X = 'Y'. For each of those IDs, I need to look up some stuff in a different table:
If the ID does not exist, it gets no row in the final result.
If the ID does exist, I want to do some logic to figure out if it gets a row. For simplicity, assume that the logic is: if column Q > 0.
So the final result is simply a column of IDs, throwing out some because they are disqualified for one of two reasons as above.
thanks.
This is what JOINs are made for.
SELECT table1.* FROM table1
INNER JOIN table2
ON table1.ID = table2.table1_ID
AND table2.Q > 0;
This will select all records in table1 (which have IDs) and then remove any records that do not have a matching record in table2 or do not have a Q > 0.
If I got your question right this might be what you are looking for:
select id from your_table
where X = 'Y'
and id in (select id from other_table where Q > 0)
You can use a subquery:
SELECT id FROM table1 WHERE table1.id IN (SELECT q FROM table2 WHERE table2.q > 0) AND table1.x='y'
SQL will check to see if the results from the outermost query are in the subquery (the part in parentheses) and won't return anything if they aren't.

How do I Write a SQL Query With a Condition Involving a Second Table?

Table1
...
LogEntryID *PrimaryKey*
Value
ThresholdID - - - Link to the appropriate threshold being applied to this log entry.
...
Table2
...
ThresholdID *PrimaryKey*
Threshold
...
All fields are integers.
The "..." thingies are there to show that these tables hold a lot more imformation than just this. They are set up this way for a reason, and I can't change it at this point.
I need write a SQL statement to select every record from Table1 where the Value field in that particular log record is less than the Threshold field in the linked record of Table2.
I'm newish to SQL, so I know this is a basic question.
If anyone can show me how this SQL statement would be structured, it would be greatly appreciated.
SELECT T1.*
FROM Table1 T1
JOIN Table2 T2 ON T2.ThresholdID = T1.ThresholdID
WHERE T2.Threshold > T1.Value
SELECT t1.*
FROM dbo.Table1 t1 INNER JOIN dbo.Table2 t2 ON t1.ThresholdID = t2.ThresholdID
WHERE t2.Threshold > t1.Value
SELECT * from table1 t1 join table2 t2 on (t1.thresholdId = t2.thresholdId)
where t1.value < t2.threshold;
SELECT t1.LogEntryID, t1.Value, t1.ThresholdID
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.ThresholdID = t2.ThresholdID
WHERE t1.Value < t2.threshold
SELECT * FROM Table1
JOIN Table2
ON table1.ThresholdID = table2.ThresholdID --(assuming table 2 holds the same value to link them together)
WHERE
value < thresholdvalue
A 'JOIN' connects 2 tables based on the 'ON' clause (which can be multipart, using 'AND' and 'OR')
If you have 3 entries in table 2 which share table1's primary key (a one-to-many association) you will receive 3 rows in your result set.
for the tables below, for example:
Table 1:
Key Value
1 Hi
2 Bye
Table 2:
Table1Key 2nd_word
1 You
1 fellow
1 friend
2 now
this query:
SELECT * FROM Table1
JOIN Table2
on table1.key = table2.table1key
gets this result set:
Key Value Table1Key 2nd_word
1 Hi 1 You
1 Hi 1 fellow
1 Hi 1 friend
2 Bye 2 now
Note that JOIN will only return results when there is a match in the 2nd table, it will not return a result if there is no match. You can LEFT JOIN for that (all fields from the second table will be NULL).
JOINs can also be strung together, the result from the previous JOIN is used in place of the original table.