Modifying a SELECT query - sql

I have a query like this:
SELECT initials, name
FROM employee e, projects p
WHERE e.country = p.country
Until now, both tables used an abbreviation for the country columns. Like "SWE" for Sweden and "ITA" for Italy.
In the future, the employee table will use names for the country columns. Like "Sweden" and "Italy".
Is it somehow possible to change my query so it can match abbreviations with names? Like "SWE" = "Sweden" and "ITA" = "Italy".
Thanks.

It would be better to have an own country table and the other tables referencing to that.
country table
-------------
id
name
abbreviation

I'd say the best solution is creating a third table where you match the current abbreviation with the full country name. You can then join both tables on that.
CountryTable (countryAbbreviation, countryName)
The select would then be something like this:
SELECT initials, name
FROM employee e JOIN countryTable c ON c.countryName = c.country
JOIN projects p ON p.country = c.countryAbbreviation

Although I fafor the solution by juergen, another solution will be altering the two tables to the new format.
UPDATE employee
SET country = "SWEDEN"
WHERE country = "SWE"
Do this for all the countries you have.

Always in country table, if country name starts with first three letters of the country in the employee table then you can use substring operator
SELECT initials, name
FROM employee e, projects p
WHERE upper(substring(e.country,1,3)) = upper(p.country)

Related

SQL connecting 3 seperate tables using procedures

I'm struggling with SQL a bit, so far I have 3 tables:
CUSTOMER
id,
name,
surname,
gender,
birthdate
GENDER
id,
gender
ADRESS
id,
country,
city
I need to create a procedure on connecting these 3 tables into a big one, so it would have (customer id, name, gender, country)
I know that I have to use joins but I am so unfamiliar with SQL.
You should just use a JOIN we use a JOIN on 2 or more tables in order to fetch some common attributes related values of one table that exists in other as together. So, here the sql then would look like. Also you dont require the gender seperate table as you have gender already present in your customer table
Select
c.id, c.name, c.gender, a.country
From CUSTOMER c
Join
Address a
On c.id =a.id

Join two tables and select a row using foreign key SQL query

I have two tables Cities and Country. I am using the query
SELECT *
FROM citiesTable
WHERE cityName LIKE 'F%'
LIMIT 30
Each cityName has their respective country joined with foreign key in country table.
I want to select each city with and their respective country like Fayzabad , Afghanistan. Which query should I use? Please mention must since I am new to SQL
Better use left join to get all city table data
select city.*, ctry.countryName
from citytable city
left join country ctry on city.countryid = ctry.countryid
Use join query
SELECT *
FROM citiesTable, country
WHERE country.country_id = citiesTable.country_id
AND cityName LIKE 'F%' LIMIT 30
Try this query:
SELECT *
FROM CitiesTable a, Country b
WHERE a.country_id = b.id
AND a.cityName LIKE 'F%'
LIMIT 30

Sql query for extracting info from one table based on other

I have two tables
Country with countryid and countryname
City with cityid and cityname
I want to extract city names based on the countryid I select.
I'm very new to sql database and please help me with direct query if you can.
Thank you very much.
According to the table structure which you showed, this query is not possible. You need to add a 'country_id' to the cities table so that you know in which country is each city. Once this has been done, your query would be
select cities.cityname, countries.countryname
from cities inner join countries on countries.country_id = cities.country_id
order by countries.countryname, cities.cityname
First you should have countryid in city table as a country can have many cities. Then you can write.
select A.cityname from city A
where
A.countryid in (select B.countryid from country B)
Please check this link if you want to find out more.
SQL: Select from one table matching criteria in another?
You have to add a countryid in City table and write the following query
select * from city c left outer join country co on c.countryid=co.countryid;
You need to have the countryid in the city table.
SELECT cityid, cityname FROM city WHERE countryid = $CounrtyID

Selecting distinct value pairs in EAV

I'm working on a user database where the profile data has been changed from a simple table into a Entity-Attribute-Value table.
Where as before the structure was along these lines:
userid (int)
address 1 (varchar)
city (varchar)
country (varchar)
It's now along these lines:
userid (int)
key (varchar)
value (varchar)
eg
userid key value
150 city London
150 country UK
151 city New York
151 country USA
152 country Mexico
I need to get a distinct list of city / country pairs and a count of all users for each country:
city country count
London UK 18
New York USA 25
There is no guarantee each key value pair will exist for each user, i.e there could be city, or country or both or neither as well as any number of other key values pairs.
This was straightforward with the old structure, but I can't even think how to begin on this, and would be grateful for some pointers
Your best solution is to go back to the traditional table because EAV makes most querying much harder than it should be - witness your problems here. You're going to be doing self-joins until you're sick of them, remanufacturing the table structure that allows you to perform sensible queries.
Cities and countries for each user ID:
SELECT a.userID, a.value AS city, b.value AS country
FROM EAV AS a
JOIN EAV AS b ON a.UserID = b.UserID
WHERE a.key = 'city'
AND b.key = 'country';
So, you end up with:
SELECT city, country, count(*)
FROM (SELECT a.userID, a.value AS city, b.value AS country
FROM EAV AS a
JOIN EAV AS b ON a.UserID = b.UserID
WHERE a.key = 'city'
AND b.key = 'country'
) AS c
GROUP BY city, country;
If there's a chance that someone might have two city or two country records, this will give you a Cartesian product with as many rows for that user as the product of the number of city and country records for that user.
This quite deliberately and consciously ignores users who have a city and no country or a country and no city (let alone those who have neither). Extending the solution to deal with those is only modestly painful - you end up with a 3-way UNION, I think, though you might be able to devise something with multiple left outer joins. But the fact that data can be entered into an EAV system without the necessary constraints to ensure that there is a city and a country for a user is simply one of the many reasons for rejecting EAV.
I'm sorry you had this foisted on you. I recommend looking at http://careers.stackoverflow.com/ as a way out of your pain, for this is only the beginning of it.
Dealing with users without either city or country or both. I think this will more or less do it:
SELECT a.userID, b.value AS city, c.value AS country
FROM (SELECT DISTINCT UserID FROM EAV) AS a
LEFT JOIN EAV AS b ON a.UserID = b.UserID
LEFT JOIN EAV AS c ON a.UserID = c.UserID
WHERE b.key = 'city'
AND c.key = 'country';
This should give you one record per user as long as there are no multiple city or country records for that user. The a scan gives you the list of unique user IDs that exist in the EAV table; the two outer joins give you the corresponding city or cities and corresponding country or countries for each such user ID, with nulls being generated if there is no city record or country record (or both) for the given user ID.
re: I need to get a distinct list of city / country pairs
SELECT DISTINCT country,city
FROM
(SELECT DISTINCT userid, VALUE AS country FROM TABLE WHERE KEY = 'country') country INNER JOIN
(SELECT DISTINCT userid, VALUE AS city FROM TABLE WHERE KEY = 'city') city ON
country.userid = city.userid
--count of all users for each country
SELECT VALUE AS country,
COUNT(DISTINCT userid) AS user_count
FROM TABLE
WHERE KEY = 'country'
GROUP BY
VALUE

What is wrong with this database query?

I have the following tables in a database (i'll only list the important attributes):
Person(ssn,countryofbirth)
Parents(ssn,fatherbirthcountry)
Employment(ssn, companyID)
Company(companyID, name)
My task is this: given fatherbirthcountry as input, output the names of companies where persons work whose countryofbirth match the fatherbirthcountry input.
I pretend that the fatherbirthcountry is Mexico and do this:
SELECT name
FROM Company
WHERE companyid = (SELECT companyid
FROM Employment
WHERE ssn = (SELECT ssn
FROM Person
WHERE countryofbirth = 'Mexico');
but it is giving me an error:
>Scalar subquery is only allowed to return a single row.
am I completely off track? Can anybody please help?
The problem is that your subqueries are returning multiple results, so you have to use where in vs. =.
Change where ssn = to where ssn in, and where companyid = to where companyid in.
try using the IN keyword not '='.
try changing your query to this
SELECT name
FROM Company
WHERE companyid IN (SELECT companyid
FROM Employment
WHERE ssn IN (SELECT ssn
FROM Person
WHERE countryofbirth = 'Mexico');
Use:
SELECT c.name
FROM COMPANY c
JOIN EMPLOYMENT e ON e.companyid = c.companyid
JOIN PERSON p ON p.ssn = e.ssn
AND p.countryofbirth = 'Mexico'
You should use In in the where condition since the (SELECT ssn
FROM Person
WHERE countryofbirth = 'Mexico'); may return multiple ssn values.
SELECT name
FROM Company
WHERE companyid = (SELECT companyid
FROM Employment
WHERE ssn IN (SELECT ssn
FROM Person
WHERE countryofbirth = 'Mexico');
Try using IN instead of =
When you write:
select a from T where a = ( select....)
The sub-query must return a single value. In case if it returns multiple values, you get your error.
To solve this we use the IN operator which allows the sub-query to return a set of value (>=0) and your where condition succeeds if a equals any one of those values.
select a from T where a IN ( select....)
See if this works
SELECT c.Name FROM PERSON p
LEFT JOIN Employment e ON p.ssn=e.ssn
LEFT JOIN Company c ON
e.CompanyID=c.CompanyID WHERE
p.countryofbirth=
The error is due to the fact that the one of the two subqueries are returning multiple rows. I would think it likely that you have multiple people born in Mexico for example.
Select Name
From Companies
Where Exists(
Select 1
From Employment
Join Person
On Person.SSN = Employment.SSN
Join Parents
On Parents.SSN = Person.SSN
Where Parents.FatherBirthCountry = Person.CountryOfBirth
And Parents.FatherBirthCountry = #InputParam
And Employment.CompanyId = Companies.CompanyId
)
Ideally use the answer from OMG Ponies using JOINs.
But if you do not like JOINs for whatever reason, then TOP 1 should do the trick for you:
SELECT name
FROM Company
WHERE companyid =(SELECT TOP 1 companyid
FROM Employment
WHERE ssn = ( SELECT TOP 1 ssn
FROM Person
WHERE countryofbirth = 'Mexico');