How to select only rows that are not in another table without getting data of the other table - PLSQL - sql

Im trying to SELECT all rows from one table with a specific condition. Im using Oracle PLSQL.
I have two tables:
Books
id
name
Page
id
words
book_id
One book can have multiple pages.
I want to find all books that don't have any page with 50 words.
The only solution I've found is to make a Left Outer Join and then filter by nulls.
Select * from Books b
LEFT OUTER JOIN Page p on b.id = p.book_id and p.words = 50
where p.words is null
I think its not a good solution, but it works, do you know any other way to do that?
I don't want to take any information about Pages. If I make a normal join and then I apply the condition I get N rows for a Book, and I only want to get 1 row for each Book
Thanks.

You could adjust your select so it is only b.*.
Possibly a more common alternative is not exists:
select b.*
from Books b
where not exists (select 1
from Page p
where b.id = p.book_id and p.words = 50
);
The two methods should have similar performance characteristics.

Related

SQL show difference between 2 tables

I know there are similar questions, but I can't find solution to what I need to do.
First of all I have 2 tables :
SD.Airlines (16k+ rows)
SD.AirlineRatings (405 rows)
I need to find which records form SD.AirlineRatings do I have in SD.Airlines, I did this :
SELECT b.Name AS Airline FROM SD.Airlines b
LEFT JOIN SD.AirlineRatings a ON a.AirlineName = b.Name
WHERE a.AirlineName IS NOT NULL;
Works fine, showed me 249/405 records. Now... If I need to compare those 249 records towards SD.AirlineRatings and check which ones I don't have.
I bet answer is simple but I don't know SQL that much.
Thanks
If you want records in AirLines ratings that are also in Airlines, then I would recommend EXISTS or IN:
select a.*
from sd.Airlines a
where exists (select 1 from sd.AirlineRatings ar where ar.AirlineName = a.Name);
If you want unrated airlines:
select a.*
from sd.Airlines a
where not exists (select 1 from sd.AirlineRatings ar where ar.AirlineName = a.Name);
And, if you want ratings on airlines that don't exist, you would swap the two tables in the query.

SQL Update - Using Multiple Table Joins

Wondering if anyone can point me in the right direction please.
I Have 3 tables...
Table A -
Code, Cost1, Cost2, Cost3
Table B -
Code, ID
Table C -
ID, Price
Basically I need to update the Price Field on Table C with (Cost1+Cost2+Cost3)
from Table A.
There is no direct link between the 2 tables, but A is linked to B via Code and B is linked to C via ID.
I can write a query to display Price and the Total Cost but can't get my head around how to do the Update.
Any pointers would be extremely welcome
Thanks
Andrew
UPDATE TC
SET Price=(TA.Cost1+TA.Cost2+TA.Cost3)
FROM TableA TA
INNER JOIN TableB TB ON TA.Code=TB.Code
INNER JOIN TableC TC ON TC.ID=TB.ID
I prefer writing my more complicated joins out first and then simply updating the alias. As you can see in the example, you could comment out the top two lines and simply put in a SELECT TC.ID,TA.Cost1+TA.Cost2+TA.Cost3 and see exactly what would change.

How to know the number difference between 2 tables in sql

I really need to know the query to display another field which is I want to name it as "number_difference" between 2 tables that required a numeric (in this case as a quantity).
I have 2 tables that totally same, let say, I modify the value from table A so some value in table A different with table B. And I want to join it into 1 table that display rows that some values were modified. I already get the result by this query :
**
select a.T1, a.T2 a.T3 ... from A where not exists (select * from B
where a.T1=b.T1 and a.T2=b.T2 and a.T3=b.T3)
**
This query works well. But, I want to add more field, the difference number between this 2 field (quantity) in 2 different tables. So let say, a.T3 and b.T3 are quantities. And want to display it as "number_difference" next to field (T2) which I display. Sorry I can't post images, they say I need at least 10 reputation to post. Please help me master, how can I make it everytime I use join/inner join it always display soo many rows that I only need the rows which a value from 1 table I have modified.
Thanks in advance.
You can get something like this
Select * From A Where A.id not in( Select Id from B)
or
Select A.* From A left join B on A.id = B.id Where A.id <> B.id
If you are specifically targeting a situation with two identical tables, where one underwent UPDATE operations only (no INSERT), and you want to identify those records which were modified, then:
select a.* from a, b where a.id=b.id and ( a.c1!=b.c1 or a.c2!=b.c2)

Select all in table where a column in table 1 exists in another table and a second column equals a variable in second table

I know the title is confusing but its the best I could explain it. Basically im developing a cinema listings website for a company which owns two cinemas. So I have a database which has the two tables "Films" and "Listings" with data for both cinemas in them.
I'm trying to select all films and their data for one cinema if the films name shows up in the listings (since the two cinemas share all films but in the table but the may not have the same films showing)
Here is what i have come up with but I run into a problem as when the "SELECT DISTINCT" returns more than one result it obviously cant be matched with the FilmName on tbl Films.
How can i check this value for all FilmNames on tblFilms?
SELECT *
FROM tblFilms
WHERE FilmName = (SELECT DISTINCT FilmName FROM tblListings WHERE Cimema = 1)
use IN if the subquery return multiple values,
SELECT *
FROM tblFILMS
WHERE FilmName IN (SELECT DISTINCT FilmName FROM tblListings WHERE Cimema = 1)
Another way to solve thius is by using JOIN (which I recommend)
SELECT DISTINCT a.*
FROM tblFILMS a
INNER JOIN tblListings b
ON a.FilmName = b.FilmName AND
b.Cimema = 1
for faster query execution, add an INDEX on FilmName on both tables.
If you have your schemas for the tables, that would help.
That said, I believe what you want to look at is the JOIN keyword. (inner/outer/left/etc). That's exactly what JOIN is meant to do (ie your title).

Select based on the number of appearances of an id in another table

I have a table B with cids and cities. I also have a table C that has these cids with extra information. I want to list all the cids in table C that are associated with ALL appearances of a given city in Table B.
My current solution relies on counting the number of times the given city appears in Table B and selecting only the cids that appear that many times. I don't know all the SQL syntax yet, but is there a way to select for this kind of pattern?
My current solution:
SELECT Agents.aid
FROM Agents, Customers, Orders
WHERE (Customers.city='Duluth')
AND (Agents.aid = Orders.aid)
AND (Customers.cid = Orders.cid)
GROUP BY Agents.aid
HAVING count(Agents.aid) > 1
It only works because I know right now with the HAVING statement.
Thanks for the help. I wasn't sure how to google this problem, since it's pretty specific.
EDIT: I'm pinpointing my problem a bit. I need to know how to determine if EVERY row in a table has a certain value for a field. Declaring a variable and counting the rows in a sub-selection and filtering out my results by IDs that appear that many times works, but It's really ugly.
There HAS to be a way to do this without explicitly count()ing rows. I hope.
Not an answer to your question, but a general improvement.
I'd recommend using JOIN syntax to join your tables together.
This would change your query to be:
SELECT Agents.aid
FROM Agents
INNER JOIN Orders
ON Agents.aid = Orders.aid
INNER JOIN Customers
ON Customers.cid = Orders.cid
WHERE Customers.city='Duluth'
GROUP BY Agents.aid
HAVING count(Agents.aid) > 1
What variant of SQL are you using?
To start with, you can (and should) use JOIN instead of doing it in the WHERE clause, e.g.,
select Agents.aid
from Agents
join Orders on Agents.aid = Orders.aid
join Customers on Customers.cid = Orders.cid
where Customers.city = 'Duluth'
group by Agents.aid
having count(Agents.aid) > 1
After that, I'm afraid I might be a little lost. Using the table names in your example query, what (in English, not pseudocode) are you trying to retrieve? For example, I think your sample query is retrieving the PK for all Agents that have been involved in at least 2 Orders involving Customers in Duluth.
Also, some table definitions for Agents, Orders, and Customers might help (then again, they might be irrelevant).
I'm not sure if I understood you problem, but I think the following query is what you want:
SELECT *
FROM customers b
INNER JOIN orders c USING (cid)
WHERE b.city = 'Duluth'
AND NOT EXISTS (SELECT 1
FROM customers b2
WHERE b2.city = b.city
AND b2.cid <> cid);
Probably you will need some indexes on these columns.