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

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).

Related

SQL select with three tables

Hi guys I'm new with databases and I'm trying to make a query where I join 3 tables. I could make it and I want to clean up the result. I want to know how can I delete the column "pin" from users table and maybe some "ids" columns.
Select * from "wish-list"
Join products
On "wish-list".id = products.holiday_id
Join users
On "wish-list".user_id = users.id
Where "wish-list".id = 1
You need to specify which columns you really need in your output. At the moment you are using
SELECT * which outputs all columns of all joined tables.
Here is what it should look like:
SELECT holiday, products.description, users.pin FROM "wish-list"
JOIN products ON "wish-list".id = products.holiday_id
JOIN users ON "wish-list".user_id = users.id
WHERE "wish-list".id = 1
It's important that you reference all columns which are not your main entity (here wish-list) with tablename.column (products.description and not only description). It will work without referencing strictly but only if the column name is unique in your query.
Furthermore you can rename columns. This is useful for example if you want to get the id's of the product table and the wish-list table.
SELECT product.id AS product_id, id AS wishlist_id FROM "wish-list"
...
Hope that helps!

How to join two tables with unrelated columns SQL

I am trying to join two tables together using UNION (although im not sure that is the best option) there are technically two related columns however they don't have the same name so i'm assuming that isn't an option here is my query:
SELECT title, type, release_date FROM pictures
UNION
SELECT name, residence, NULL as Col3 FROM actor
ORDER BY release_date ASC;
It is only printing out the pictures columns from this? Thank you for any help in advance.
To relate two tables you could use some foreign key or a third table in the case of beign a many-to-many relation, you should use one of the join options, for example:
Imagine that exists a table that relate actor and pictures, called actor_pictures.
Image that we will relate the tables by id (it could be another one, and it doesn't have to have the same name).
You could do this:
SELECT * FROM actor_pictures ap
JOIN actor a ON ap.actor_id = a.id
JOIN pictures p ON ap.pictures_id = p.id
ORDER BY p.release_date ASC
Read this: https://www.w3schools.com/sql/sql_join.asp

Querying records that meet muliple criteria

Hi I’m trying to write a query and I’m struggling to figure out how to go about it.
I have a suppliers table and a supplier parts table I want to write a query that lists suppliers that have specified related Parts in the supplier parts table. If a supplier doesn’t have all specified related parts then they should not be listed.
At the moment I have written a very basic query that lists the supplier if they have a related supplier part that meets the criteria.
SELECT id ,name
FROM
efacdb.dbo.suppliers INNER JOIN [efacdb].[dbo].[spmatrix] ON
id = spmsupp
WHERE spmpart
IN ('ALUM_5083', 'ALUM_6082')
I only want to show the supplier if they have both parts related. Does anyone know how I could do this?
Use a subquery with counting distinct occurences:
select * from suppliers s
where 2 = (select count(distinct spmpart) from spmatrix
where id = spmsupp and spmpart in ('ALUM_5083', 'ALUM_6082'))
As a note, you can modify your query to get what you want, just by using an aggregation:
SELECT id, name
FROM efacdb.dbo.suppliers INNER JOIN
[efacdb].[dbo].[spmatrix]
ON id = spmsupp
WHERE spmpart IN ('ALUM_5083', 'ALUM_6082')
GROUP BY id, name
HAVING MIN(spmpart) <> MAX(spmpart);
If you know there are no duplicates, then having count(*) = 2 also solves the problem.

select * with column(s) from different table merging with that of original table's columns

These are my tables(with some records):
Product:
ID PRICE NAME DESCRIPTION
1 100 laptop laptop_desc
2 200 mouse mouse_desc
3 300 伊吾 伊吾伊吾
Product_Translations:
PID LANG NAME DESCRIPTION
1 ch 伊吾 伊吾伊吾
And using the following query I could JOIN the 2 tables:
SELECT p.id,p.price,
COALESCE(pt.Name, p.Name) Name,
COALESCE(pt.Description, p.Description) Description
FROM Product p
LEFT JOIN Product_T pt
ON pt.PID = p.ID
AND pt.LANG = 'ch'
WHERE (UPPER(p.name) LIKE UPPER('%伊吾%') OR UPPER(pt.name) LIKE UPPER('%伊吾%'))
Now my question is that in the above query I need to mention each and every column in the select query explicitly(like p.id, p.price; real table has lot more columns) which I don't want to do. In my case I need to get all columns all the time, i.e, select *. But If give p.* in the query, name and description columns are coming twice which is expected(from Product and Product_T tables). So is there any way I could still give p.* and get the merged name and description columns ?
Thanks for your help.
You could query the schema to find the columns on your tables and then dynamically build your select statement from that. (E.g. if a column with the same name appears in both tables only select it from one of them).
See http://hsqldb.org/doc/2.0/guide/databaseobjects-chapt.html#dbc_information_schema for information on how to query the schema in hsqldb.

Some SQL Questions

I have been using SQL for years, but have mostly been using the query designer within SQL Studio (etc.) to put together my queries. I've recently found some time to actually "learn" what everything is doing and have set myself the following fairly simple tasks. Before I begin, I'd like to ask the SOF community their thoughts on the questions, possible answers and any tips they may have.
The questions are;
Find all records w/ a duplicate in a particular column (e.g. a linking id is in more than 1 record throughout table)
SUM price from a linked table within the same query (select within a select?)
Explain the difference between the 4 joins; LEFT, RIGHT, OUTER, INNER
Copy data from one table to another based on SELECT and WHERE criteria
Input welcomed & appreciated.
Chris
I recommend that you start by following some tutorials on this topic. Your questions are not uncommon questions for someone moving from a beginner to intermediate level in SQL. SQLZoo is an excellent resource for learning SQL so consider following that.
In response to your questions:
1) Find all records with a duplicate in a particular column
There are two steps here: find duplicate records and select those records. To find the duplicate records you should be doing something along the lines of:
select possible_duplicate_field, count(*)
from table
group by possible_duplicate_field
having count(*) > 1
What we're doing here is selecting everything from a table, then grouping it by the field we want to check for duplicates. The count function then gives me a count of the number of items within that group. The HAVING clause indicates that we want to filter AFTER the grouping to only show the groups which have more than one entry.
This is all fine in itself but it doesn't give you the actual records that have those values on them. If you knew the duplicate values then you'd write this:
select * from table where possible_duplicate_field = 'known_duplicate_value'
We can use the SELECT within a select to get a list of the matches:
select *
from table
where possible_duplicate_field in (
select possible_duplicate_field
from table
group by possible_duplicate_field
having count(*) > 1
)
2) SUM price from a linked table within the same query
This is a simple JOIN between two tables with a SUM of the two:
select sum(tableA.X + tableB.Y)
from tableA
join tableB on tableA.keyA = tableB.keyB
What you're doing here is joining two tables together where those two tables are linked by a key field. In this case, this is a natural join which operates as you would expect (i.e. get me everything from the left table which has a matching record in the right table).
3) Explain the difference between the 4 joins; LEFT, RIGHT, OUTER, INNER
Consider two tables A and B. The concept of "LEFT" and "RIGHT" in this case are slightly clearer if you read your SQL from left to right. So, when I say:
select x from A join B ...
The left table is "A" and the right table is "B". Now, when you explicitly say "LEFT" the SQL statement you are declaring which of the two tables you are joining is the primary table. What I mean by this is: Which table do I scan through first? Incidentally, if you omit the LEFT or RIGHT, then SQL implicitly uses LEFT.
For INNER and OUTER you are declaring what to do when matches don't exist in one of the tables. INNER declares that you want everything in the primary table (as declared using LEFT or RIGHT) where there is a matching record in the secondary table. Hence, if the primary table contains keys "X", "Y" and "Z", and the secondary table contains keys "X" and "Z", then an INNER will only return "X" and "Z" records from the two tables.
When OUTER is used, we're saying: Give me everything from the primary table and anything that matches from the secondary table. Hence, in the previous example, we'd get "X", "Y" and "Z" records in the output record set. However, there would be NULLs in the fields which should have come from the secondary table for key value "Y" as it doesn't exist in the secondary table.
4) Copy data from one table to another based on SELECT and WHERE criteria
This is pretty trivial and I'm surprised you've never encountered it. It's a simple nested SELECT in an INSERT statement (this may not be supported by your database - if not, try the next option):
insert into new_table select * from old_table where x = y
This assumes the tables have the same structure. If you have different structures then you'll need to specify the columns:
insert into new_table (list, of, fields)
select list, of, fields from old_table where x = y
Let's say you have 2 tables named :
[OrderLine] with the columns [Id, OrderId, ProductId, Qty, Status]
[Product] with [Id, Name, Price]
1) all orderline of command having more than 1 line (it's technically the same as looking for duplicates on OrderId :) :
select OrderId, count(*)
from OrderLine
group by OrderId
having count(*) > 1
2) total price for all order line of the order 1000
select sum(p.Price * ol.Qty) as Price
from OrderLine ol
inner join Product p on ol.ProductId = p.Id
where ol.OrderId = 1000
3) difference between joins:
a inner join b => take all a that has a match with b. if b is not found, a will be not be returned
a left join b => take all a, match them with b, include a even if b is not found
a righ join b => b left join a
a outer join b => (a left join b) union ( a right join b)
4) copy order lines to a history table :
insert into OrderLinesHistory
(CopiedOn, OrderLineId, OrderId, ProductId, Qty)
select
getDate(), Id, OrderId, ProductId, Qty
from
OrderLine
where
status = 'Closed'
To answer #4 and to perhaps show at least some understanding of SQL and the fact this isn't HW, just me trying to learn best practise;
SET NOCOUNT ON;
DECLARE #rc int
if #what = 1
BEGIN
select id from color_mapper where product = #productid and color = #colorid;
select #rc = ##rowcount
if #rc = 0
BEGIN
exec doSavingSPROC #colorid, #productid;
END
END
END