Inner join (or intersect) over three tables - sql

I have a database with three tables named: NameAddressPhone, NameAddressAge, and AgeSex.
Table NameAddressPhone has columns name, address, and phone.
Table NameAddressAge has columns name, address, and age.
Table AgeSex has columns age and sex.
I'm trying to write a (SQLite) query to find the names, addresses, and ages such that the names and addresses appear in both NameAddressPhone and NameAddressAge, and such that the ages appear in both NameAddressAgeand AgeSex. I'm able to get halfway there (i.e., with two tables) using inner join, but I only dabble in SQL and would appreciate some help from an expert in getting this right. I have seen solutions that appear to be similar, but don't quite follow their logic.
Thanks in advance.
Chris

I think you just want to join these together on their obvious keys:
select *
from NameAddressPhone nap join
NameAddressAge naa
on nap.name = naa.name and
nap.address = naa.address join
(select distinct age
from AgeSex asx
) asx
on asx.age = naa.age
This is selecting the distinct ages in the AgeSex to prevent the proliferation of rows. Presumably, one age could appear multiple times in that table, which would result in duplicate rows on output.

I am assuming your tables have the following layout
NameAddressPhone
================
Name
Address
Phone
NameAddressAge
==============
Name
Address
Age
AgeSex
======
Age
Sex
If I am understanding everything correctly, the solution might look kind of like this:
SELECT P.Name, P.Address, P.Phone, A.Age, S.Sex
FROM NameAddressPhone P
INNER JOIN NameAddressAge A ON P.Name = A.Name AND P.Address = A.Address
INNER JOIN AgeSex S ON A.Age = S.Age
Mind you, joining AgeSex could produce duplicate rows if there are multiple rows with the same age in AgeSex. There wouldn't be a way to distinguish 21 and Male from 21 and Female, for example.
I hope I can help and this is what you are looking for.

Related

sql query counting something across three tables

I have three tables with some columns shown below:
Table 1 - airports: NAME IATA, COUNTRY
Table 2 - airlines: NAME, IATA
Table 3 - routes: AIRLINE, SOURCE AIRPORT, DESTINATION AIRPORT
I want to write an SQLite query which finds out how many countries certain airlines fly to.
Here's what I've got so far:
SELECT al.NAME AS 'Airline Name',
COUNT(r.AIRLINE) AS 'No. of Destinations'
FROM airlines as al
INNER JOIN routes r ON r.AIRLINE = al.IATA
INNER JOIN airports ap ON r.DESTINATION_AIRPORT = ap.IATA
GROUP BY ap.COUNTRY
ORDER BY [No. of Destinations] DESC;
I'm getting an incredibly wrong result. Help would be appreciated please and thank you. (those joins are the links between the tables for those who want to try and write a query for me)
There are two major problems with your query:
The SELECT columns are inconsistent with the GROUP BY.
You are not counting the countries, which seems to be what you want.
Tweaking your query fixes this problem:
SELECT al.NAME AS Airline_Name,
COUNT(DISTINCT cp.country) AS num_countries
FROM airlines al INNER JOIN
routes r
ON r.AIRLINE = al.IATA INNER JOIN
airports ap
ON r.DESTINATION_AIRPORT = ap.IATA
GROUP BY al.name;
Note: I strongly discourage you from using single quotes for column names. The simplest approach is to use column names that don't require escaping. Then only use single quotes for string and date constants.

Find potential duplicate names in database

I have two tables in a SQL Server Database:
Table: People
Columns: ID, FirstName, LastName
Table: StandardNames
Columns: Nickname, StandardName
Sample Nicknames would be Rick, Rich, Richie when StandardName is Richard.
I would like to find duplicate contacts in my People table but replace any of the nicknames with the standard name. IE: sometimes I have Rich Smith other times it is Richard Smith in the People table. Is this possible? I realize it might be multiple joins to the same table but can't figure out how to start.
Firstly, you need to determine how many duplicates you have in your People table...
SELECT p.FirstName, COUNT(*)
FROM People AS p
INNER JOIN StandardNames AS sn
ON CHARINDEX(sn.Nickname, p.FirstName) > 0 OR
CHARINDEX(sn.Nickname, p.LastName) > 0
GROUP BY p.FirstName
HAVING COUNT(*) > 1
That's just to get an idea of what data you're trying to find in relation to the Nicknames that may possibly exist inside (as a wildcard word search) the Firstname and Lastname columns.
If you are happy with the items found then expand on the query to update the values.
Let's say you wanted to change the Firstname to be the Standardname...
UPDATE p2
SET p2.FirstName = p2.Standardname
FROM
(SELECT p.ID, sn.StandardName
FROM People AS p
INNER JOIN StandardNames AS sn
ON CHARINDEX(sn.Nickname, p.FirstName) > 0 OR
CHARINDEX(sn.Nickname, p.LastName) > 0) AS a
INNER JOIN People AS p2 ON p2.ID = a.ID
So this will obviously find all the People IDs that have a match based on the query above, and it will update the People table by replacing the FirstName with the StandardName.
However, there are issues with this due to the limitation of your question.
the StandardNames table should have its own ID field. All tables should have an ID column as its primary table. That's just my view.
this is only going to work for data it matches using the CHARINDEX() function. What you really need is something to find based on a "sound" or similarity to the nicknames. Check out the SOUNDEX() function and apply your logic from there.
And this is assuming your IDs above are unique!
Good luck
You could standardize the names by joining, and count the number of occurrences. Extracting the ID is a bit fiddly, but also quite possible. I'd suggest the following - use a case expression to find the contact with the standard name, and if you don't have one, just take the id of the first duplicate:
SELECT COALESCE(MIN(CASE FirstName WHEN StandardName THEN id END), MIN(id)),
StandardName,
LastName,
COUNT(*)
FROM People p
LEFT JOIN StandardNames s ON FirstName = Nickname AND
GROUP BY StandardName, LastName

SQL Query multiple tables same values

I'm having an issue creating a query. Here are the specifics.
There are 2 tables company_career and company_people.
People contains person information (Name, Address, etc) and Career contains historical career information (job_title, department, etc.)
People is linked to Career by job_ref_id.
Direct_Report_id lies in the career table and contains a unique id that correlates to job_ref_id.
Example: job_ref_id = '1' results in direct_report_id ='A'. I then use the value produced from direct-report_id (i.e., 'A') and query the job_ref_id = 'A' and this produces the employee name. Since it produces the employee name (which is actually the manager) I need to know how I would query this to present this as the manager name.
I think I know what you are looking for, you just need to use joins and aliases. For example:
SELECT
cp.name AS [EmployeeName],
cp.address AS [EmployeeAddress],
cc.job_title AS [EmployeeTitle],
cc.department AS [EmployeeDept],
m.name AS [ManagerName]
FROM company_people cp
LEFT JOIN company_career cc ON cc.job_ref_id = cp.job_ref_id
LEFT JOIN company_people m ON m.job_ref_id = cc.direct_report_id

SQL WHERE <from another table>

Say you have these tables:
PHARMACY(**___id_pharmacy___**, name, addr, tel)
PHARMACIST(**___Insurance_number___**, name, surname, qualification, **id_pharmacy**)
SELLS(**___id_pharmacy___**, **___name___**, price)
DRUG(**___Name___**, chem_formula, **id_druggistshop**)
DRUGGISTSHOP(**___id_druggistshop___**, name, address)
I think this will be more specific.
So, I'm trying to construct an SQL statement, in which I will fetch the data from id_pharmacy and name FROM PHARMACY, the insurance_number, name, and surname columns from PHARMACIST, for all the pharmacies that sell the drug called Kronol.
And that's basically it. I know I'm missing the relationships in the code I wrote previously.
Note: Those column names which have underscores left and right to them are underlined(Primary keys).
The query you've written won't work in any DBMS that I know of.
You'll most likely want to use some combination of JOINs.
Since the exact schema isn't provided, consider this pseudo code, but hopefully it will get you on the right track.
SELECT PH.Ph_Number, PH.Name, PHCL.Ins_Number, PHCL.Name, PHCL.Surname
FROM PH
INNER JOIN PHCL ON PHCL.PH_Number = PH.Ph_Number
INNER JOIN MLIST ON MLIST.PH_Number = PH.PH_Number
WHERE MLIST.Name = "Andy"
I've obviously assumed some relationships between tables that may or may not exist, but hopefully this will be pretty close. The UNION operator won't work because you're selecting different columns and a different number of columns from the various tables. This is the wrong approach all together for what you're trying to do. It's also worth mentioning that a LEFT JOIN may or may not be a better option for you, depending on the exact requirements you're trying to meet.
Ok, try this query:
SELECT A.id_pharmacy, A.name AS PharmacyName, B.Insurance_number,
B.name AS PharmacistName, B.surname AS PharmacistSurname
FROM PHARMACY A
LEFT JOIN PHARMACIST B
ON A.id_pharmacy = B.id_pharmacy
WHERE A.id_pharmacy IN (SELECT id_pharmacy FROM SELLS WHERE name = 'Kronol')

SQL subqueries - which order do you perform the SELECT statements?

I just started learning SQL a couple of days ago, and I'm trying to understand which order I should use the SELECT statement when building subqueries. Here is a simple example of what I am trying to accomplish.
I have two tables - One that specifies the demographics of a customer list, and the other that details how they heard about our company.
In the first table, my customers are listed as either Male or Female in the Gender column, and then in the next column, their ethnicity is specified (Caucasian, African American, Hispanic, etc).
In the second table, there is a Referral column that specifies how they heard about our company (TV, radio, website, etc).
I want to first filter the customers by gender (I want to show only Female data), and then I want to count how many times our customers found us through our website for each ethnicity listed in the table.
SELECT Ethnicity, COUNT(Referral)
FROM Demographics, Marketing
WHERE Demographics.id = Marketing.source_id
AND Referral = 'website'
/* confused about how to put subquery here saying Gender = 'Female' */
ORDER BY Ethnicity
Basically, I'm confused about how to properly include the subquery and if I am even filtering in the correct order.
But here is what I want my table to look like:
/*Data is shown for ONLY Females */
Referral Caucasian African American Hispanic Asian
website 7 19 14 22
I'm sorry, this code is probably really messed up. Please help if you can.
From what you've described, you don't need a subquery:
SELECT Ethnicity, COUNT(Referral)
FROM Demographics, Marketing
WHERE Demographics.id = Marketing.source_id
AND Referral = 'website'
AND Gender = 'Female'
ORDER BY Ethnicity
...note that this gives you a different resultset from the one you've shown, though, with ethnicity, count on each row.
When you are using two table u must use the INNER JOIN syntax:
http://w3schools.com/sql/sql_join_inner.asp
SELECT Ethnicity, COUNT(Referral)
FROM Demographics INNER JOIN Marketing
...
AND Referral = 'website'
AND Gender = 'Female'
...