Consider this DB at https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_all
The goal is to write a query to list all the cities in that DB.
Can the query below be re-written without using the union operator? in ANSI SQL or any other ones. I just want to get a general idea. Thank you
SELECT City, country FROM Customers
UNION
SELECT City, country FROM Suppliers
order by city, country
The only other way (I can think of) to do it is with a FULL OUTER JOIN:
SELECT DISTINCT
COALESCE(c.City, s.City) AS City,
COALESCE(c.country, s.country) AS country
FROM Customers c FULL JOIN Suppliers s
ON s.City = c.City AND s.country = c.country
Note that UNION is the correct method for this requirement and that FULL OUTER JOIN is not supported by databases like MySql and SQLite.
Related
I need to write SQL query like:
Show all countries with more than 1000 users, sorted by user count.
The country with the most users should be at the top.
I have tables:
● Table users (id, email, citizenship_country_id)
● Table countries (id, name, iso)
Users with columns: id, email, citizenship_country_id
Countries with columns: id, name, iso
SELECT countries.name,
Count(users.citiizenship_country_id) AS W1
FROM countries
LEFT JOIN users ON countries.id = users.citizenship_country_id
GROUP BY users.citiizenship_country_id, countries.name
HAVING ((([users].[citiizenship_country_id])>2));
But this does not work - I get an empty result set.
Could you please tell me what I'm doing wrong?
A LEFT JOIN is superfluous for this purpose. To have 1000 users, you need at least one match:
SELECT c.name, Count(*) AS W1
FROM countries c JOIN
users u
ON c.id = u.citizenship_country_id
GROUP BY c.name
HAVING COUNT(*) > 1000;
Notice that table aliases also make the query easier to write and to read.
Group by country name and use HAVING Count(u.citiizenship_country_id)>1000, it filters rows after aggregation:
SELECT c.name,
Count(u.citiizenship_country_id) AS W1
FROM countries c
INNER JOIN users u ON c.id = u.citizenship_country_id
GROUP BY c.name
HAVING Count(u.citiizenship_country_id)>1000
ORDER BY W1 desc --Order top counts first
;
As #GordonLinoff pointed, you can use INNER JOIN instead of LEFT JOIN, because anyway this query does not return counries without users and INNER JOIN performs better because no need to pass not joined records to the aggregation.
I have three tables customer, address, and city and I want to find the city each customer is from. So I am using two joins but after the query execution I find out that no two customers have the same city according to my query can someone please help me is my query ok.
I am using pagila database.
select c.first_name , ct.city
from customer c
join address a on c.address_id=a.address_id
join city ct on a.city_id=ct.city_id
Is this what are you expecting?
select distinct c.first_name , ct.city from customer c
join address a on c.address_id=a.address_id
join city ct on a.city_id=ct.city_id
I have two tables:
Customers (name, address, postcode (FK))
Postcodes (postcode (PK), county)
I want to find out how many customers are in each county.
I am assuming I need an inner join on postcode but don't know how to combine this with a count(customer_id) and distinct(county).
Although you can write queries with SELECT DISTINCT country it prevents you from doing aggregates such as COUNT. Instead you can use GROUP BY which broadly has the same effect as DISTINCT but with much more power and flexibility.
These two queries give the same results, but the second lets you then go on to add your JOIN and COUNT statements.
SELECT DISTINCT county FROM postcodes
SELECT county FROM postcodes GROUP BY county
By and large, don't use SELECT DISTINCT, but use this kind of pattern...
SELECT
postcodes.county,
COUNT(customers.customer_id)
FROM
postcodes
INNER JOIN
customers
ON customers.postcode = postcodes.postcode
GROUP BY
postcodes.county
Just join the Customers table to the Postcodes table on the common field 'postcode '. Then you can use Group By to get your counts and return one row per County
SELECT
County,
COUNT(Customer_Id) CustomerCount
FROM
Postcodes pc
JOIN Customers c ON pc.PostalCode = c.PostalCode
GROUP BY
County
Say, I have the following two tables:
Table customer:
id, salutation, forename, lastname, companyID
and a table company:
Company_id, Company_name, Company_address
and I want to have an evaluation over all users and their company (if they belong to one)
salutation, forename, lastname, companyName
that would amount basically to a very easy script:
select salutation, forename, lastname, company_name
from customer, company
where companyID=Company_id;
The trouble now is just, that companyID can be null. (A customer doesn't need to be part of a company). And since there is no companyID null entry in the company table and any customer who has no company ID listed is omitted due to the joint statement.
Of couse I could divide it into two scripts one for companyid=null and one for not null and mix them with a UNION command, but is there perhaps something like an if statement?
something like:
select salutation, forename, lastname, placeholder
from customer, company
where
if companyID=null then placeholder=null
else (companyID=Company_id and placeholder=company_name);
?
I know there is a case statement, that can check on the field's value and return something else instead, but is there a way to combine that with a joint to another table?
You are looking for an outer join:
select cu.salutation, cu.forename, cu.lastname, co.company_name
from customer cu
left join company co on cu.companyID = co.Company_id;
In general you should stop using the ancient implicit join syntax in the where clause and use an explicit JOIN operator. That is also the only cross-DBMS way to actually do an outer join (all DBMS that supported some proprietary outer join syntax have deprecated that)
Try this
select salutation, forename, lastname, placeholder
from customer, company
where
(companyID=null and placeholder=null )
OR
(companyID=Company_id and placeholder=company_name);
Use a left join instead of an inner join
select a.salutation, a.forename, a.lastname, a.company_name
from customer a
left outer join company b
on a.companyID=b.companyID;
I'm trying to create a select statement
I need to gather from one table a record that equals the same code used in another table.
better put, a client selects from a drop down list a city and a category for that city.
When the client clicks next, the various places in that city that meet that category are displayed.
but I can't figure out where I'm going wrong.
now when the client selects a city, there are two records that read for each city, a proper city code and a post box code that has 'bx' as the first letters
in my first query, to eliminate duplicates, I say
select c.[Description] from city c
where c.Provincecode like 'EC' and
c.citycode in (select c.citycode from City c
where SUBSTRING(c.citycode,0,3) not like 'bx')
that gives me one city name.
but now, if the client has chosen, for instance, cash only places to see,
there should only be one record showing up in the results
but try as I might, I can't get the right syntax
I've tried:
select c.[Description] from city c
where c.Provincecode like 'EC' and
c.citycode in (select c.citycode from City c
where SUBSTRING(c.citycode,0,3) not like 'bx')
and exists (select * from Customers cu
where cu.Category like 'SC' and cu.Province like 'EC')
but that brings more results than anticipated
this is done using an access database, but I am using SQL to do the coding, which I re-write into access. that's not a problem
so if someone could please provide the SQL answer, I can do the rest from there
I'm not sure if I'm supposed to do a join.
I did try
select * from
(select c.[Description] from city c
where c.Provincecode like 'EC' and
c.citycode in (select c.citycode from City c
where SUBSTRING(c.citycode,0,3) not like 'bx')) x
join Customers on province=city.provincecode where Category like 'SC'
but I get errors for multi-part identifier could not be bound
EDIT
this is the new query
select *
from
(
select c.*
from city c
where c.Provincecode like 'EC'
and c.citycode in
(
select c.citycode
from City c
where SUBSTRING(c.citycode,0,3) not like 'bx'
)
) x
join
Customers
on province=x.Provincecode
where Category like 'SC'
what is returned is
as you can see, there are too many reults that have C Strydom as the customer, but all the cities are there
for this particular example, only one record should be shown, the second one
The issue was an incomplete JOIN (see question comments for details). The query that worked was
select *
from
(
select c.*
from city c
where c.Provincecode like 'EC'
and c.citycode in
(
select c.citycode
from City c
where SUBSTRING(c.citycode,0,3) not like 'bx'
)
) x
INNER JOIN
Customers
ON Customers.province=x.Provincecode
AND Customers.city=x.Citycode
where Category like 'SC'
Although I don't like using SELECT *, you know more of the actual columns you DO want, I leave that to you. The query should be simple as you are primarily looking at the "City" table for a specific province code but doesn't start with "bx". Just have that in your where clause... you can test multiple things about a record without having to join to itself on some other criteria. Once you have that, then a simple join to the customer table for the category you are limiting to.
select *
from
city c
JOIN Customers CU
on c.ProvinceCode = CU.Province
AND CU.Category like 'SC'
where
c.ProvinceCode like 'EC'
and NOT substr( c.CityCode,0,3 ) = 'bx'
Now, your issue of the multiple records per customer. If all you are joining on is the province code to the customer table, you WILL get a Cartesian result... but if you join to the ProvinceCode AND City of the customer, you'll get only the single one that matches... but we don't have the customer table detail to confirm that column relationship.