SQL Joining on 5 Tables - Inclusion & Exclusion - sql

I want to join 5 tables to come up with 3 different result sets.
My tables are:
Customers - contains email address (unique id), email address domain name, account name, demographic info, etc (Customers)
Product 1 customer account names (Product1Accounts)
Product 1 customer email address domain names (Product1Domains)
Product 2 customer account names (Product2Accounts)
Product 2 customer email address domain names (Product2Domains)
The 3 results I need are:
Product 1 customers excluding Product 2 customers
Product 2 customers excluding Product 1 customers
Customers of both Product 1 and 2
Side Note: a customer of each product could be identified by account OR domain name.
I can create the following to come up with matches on table 1,2,3 or 1,4,5 but I am getting hung up on how to incorporate the exclusions
SELECT *
FROM Customers
INNER JOIN Product1Accounts
ON Customers.Company=Product1Accounts.Account
UNION
SELECT *
FROM Customers
INNER JOIN Product1Domains
on Customers.Email_Address_Domain=Product1Domains.Domain
I'm also not sure how to obtain the 3rd result set I am looking for... any help or advice on how to write this code better would be appreciated.

For the third result you can just keep adding UNIONs to get the additional results for the Product2 tables (which really smells like the database needs to be normalized).
For the first two results the EXCEPT keyword should work. I don't work with SQL Express, so I'm not sure if it's available in that version of SQL Server, but check it out. Your code would look like:
(
SELECT C.Company
FROM Customers C
INNER JOIN Product1Accounts PA ON PA.Account = C.Company
UNION
SELECT C.Company
FROM Customers C
INNER JOIN Product1Domains PD ON PD.Domain = C.Email_Address_Domain
)
EXCEPT
(
SELECT C.Company
FROM Customers C
INNER JOIN Product2Accounts PA ON PA.Account = C.Company
UNION
SELECT C.Company
FROM Customers C
INNER JOIN Product2Domains PD ON PD.Domain = C.Email_Address_Domain
)

I think your database structure is not correct, you are having 2 different tables for the 2 products. Does it mean that if in future you have 5 more products, you will have 5 more tables?
I think its better to remove the product1 and product2 tables and create one product table, then you can have another table that can be called productType which have the information about the type of the product and with a Foreign Key its connected to your main product Table
Also does any of your product tables have a Foreign Key available in your customers table? from what I can see they name of the columns you are trying to do the join on are not really clear to be a foreign key.

Related

How do I retrieve records from two tables that use the same PK while singling out records with a specific PK entry?

I have two tables joined by a primary key (coupon ID -as you can see in the attached picture below).
In the coupon table I have all of the existing coupons .
In the customer coupon table I have coupon id's that have been purchased by the customer id next to it.
Only coupons that have been purchased appear in the customer coupon table.
I would like to send a query in which I can retrieve all the coupons that have not been purchased by a certain customer ID.
the retrieved records can be coupons that have been purchased by other customer id's or new coupons which don't appear in the customer coupon table.
I'm currently using a derby DB which supports the following:
INNER JOIN
LEFT OUTER JOIN
RIGHT OUTER JOIN
The most straight forward approach, IMHO, would be to use the not exists operator:
SELECT *
FROM coupon c
WHERE NOTE EXISTS (SELECT *
FROM customer_coupon cc
WHERE c.id = cc.coupon_id AND
cc.customer_id = 123 /* Just an example */)

SQL in Access 2013

I have 2 tables in an MS Access 2013 database that I have pulled through an ODBC. One is called PUBLIC_PHONE_NUMBERS and the 2nd is PUBLIC_CUSTOMER. Now I need to join the two fields PHONE_ACCT and PHONE_NUMBER from the phone table to the customer table. The phone account number is the same as the customer account number, but I need each account to have its phone number listed on the customer's table as well.
Here is what I thought would work:
SELECT public_phone_numbers.phone_acct, public_phone_numbers.phone_number
FROM public_phone_numbers
INNER JOIN public_customer
ON public_phone_numbers.phone_acct = public_customer.c_acct;
not sure I understand what you need, but perhaps it's only a left outer join?
SELECT c.*, p.phone_number
FROM public_customer c
left outer JOIN public_phone_numbers p
ON c.c_acct = p.phone_acct

SQL fetch multiple values on join

Hi I have an SQL table which has two tables which make reference to the same foreign key in a separate table twice... something like
SALES table
idSales idClient1 idClient2
1 1 2
CLIENT table
idClient ClientName
1 Bob
2 Mick
I want to join the SALES table to the CLIENT table and return data as follows:
idSales idClientClientName1 idClientClientName2
1 Bob Mick
Can anyone help with the SQL for this? I'm getting ambiguous column name errors on my join.
Thank you
You need to basically join table Client on table Sales twice because there are two columns on table Sales that are dependent on table Client.
SELECT a.idSales,
b.ClientName ClientName1,
c.ClientName ClientName2
FROM Sales a
INNER JOIN Client b
ON a.idClient1 = b.idClient
INNER JOIN Client c
ON a.idClient2 = c.idClient
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
But when one of the columns or both columns are nullable, INNER JOIN will not give you all records from Sales because it will only select where it has atleast one match on the other table. Instead use LEFT JOIN.
I might add that in cases like this, I use table aliases that hint at what entity you are linking to in the joined table. If for example, the foreign keys were to an address table, and you had a work address, and a Home address, I would use tables aliases of h and w for the two joins. In your case, i.e.,
Selext s.idSales,
c1.ClientName ClientName1,
c2.ClientName ClientName2
From Sales s
Join Client c1
On c1.idClient = s.idClient1
Join Client c2
On c2.idClient = s.idClient2
For those beginner SQL folks who may see this question in the future, it's helpful to add in the AS words, it makes it clearer still:
SELECT
Sale.idSales,
c1.ClientName AS ClientName1,
c2.ClientName AS ClientName2
FROM
Sales AS Sale
INNER JOIN Client AS c1 ON Sale.idClient1 = c1.idClient
INNER JOIN Client AS c2 ON Sale.idClient2 = c2.idClient

Multiple records joined Access SQL

I'm not sure if what I want to do is possible but if it is possible, it's probably a really easy solution that I just can't figure out. Once things get to a certain complexity though, my head starts spinning. Please forgive my ignorance.
I have a database running in MS Access 2007 for a school which has a plethora of tables joined to each other. I'm trying to create a query in which I get information from several tables. I'm looking up sales and payment information for different customers, pulling info from several different linked tables. Each sale is broken down into one of 4 categories, Course Fee, Registration Fee, Book Fee and Others. Because each customer will have multiple purchases, each one is a separate entry in the Sales table. The payment information is also in its own table.
My SQL currently looks like this:
SELECT StudentContracts.CustomerID, (Customers.CFirstName & " " & Customers.CLastName) AS Name, Customers.Nationality, Courses.CourseTitle, (StudentContracts.ClassesBought + StudentContracts.GiftClasses) AS Weeks, StudentContracts.StartDate, Sales.SaleAmount, SaleType.SaleType, Sales.DueDate, Payments.PaymentAmount
FROM (
(
(Customers INNER JOIN StudentContracts ON Customers.CustomerID = StudentContracts.CustomerID)
INNER JOIN Payments ON Customers.CustomerID = Payments.CustomerID)
INNER JOIN
(SaleType INNER JOIN Sales ON SaleType.SalesForID = Sales.SalesForID)
ON Customers.CustomerID = Sales.CustomerID)
INNER JOIN
(
(Courses INNER JOIN Classes ON Courses.CourseID = Classes.CourseID)
INNER JOIN StudentsClasses ON Classes.ClassID = StudentsClasses.ClassID)
ON Customers.CustomerID = StudentsClasses.CustomerID;
This works and brings up the information I need. However, I am getting one record for each sale as in:
CustomerID Name ... SaleAmount SaleType PaymentAmount
1 Bob $600 Course $1000
1 Bob $300 RgnFee $1000
1 Bob $100 Book $1000
What I need is one line for each customer but each sale type in it's own column in the row with the sale amount listed in its value field. As so:
CustomerID Name ... Course RgnFee Book Others PaymentAmount
1 Bob $600 $300 $100 $1000
Can anyone help and possibly explain what I should/need to be doing?
Thanks in advance!
You can create a cross tab from the query you have already created. Add the query to the Query Design Grid, choose Crosstab from query types, and select a Row or rows, Column and Value.
Say:
TRANSFORM Sum(t.SaleAmount) AS SumOfSaleAmount
SELECT t.ID, t.Name, Sum(t.SaleAmount) AS Total
FROM TableQuery t
GROUP BY t.ID, t.Name
PIVOT t.SaleType
If you want a certain order, you can edit the property sheet to include column headings, or you can add an In statement to the SQL. Note that if you add column headings, a column will be included for each column, whether or not data is available, and more importantly, a column will not be included that has data, if it is not listed.
TRANSFORM Sum(t.SaleAmount) AS SumOfSaleAmount
SELECT t.ID, t.Name, Sum(t.SaleAmount) AS Total
FROM TableQuery t
GROUP BY t.ID, t.Name
PIVOT t.SaleType In ("Course","RgnFee","Book","Others");

Selecting products sold to a given set of customers

I have two tables, product and sold_record. product contains my list of products, while sold_record contains all of my transactions. How can I select a distinct list of products that both customer A and customer B bought?
If your sold_record table has a product id and customer id, then the query would be:
select distinct s1.product_id
from sold_record as s1, sold_record as s2
where s1.customer_id = "Customer A"
and s2.customer_id = "Customer B"
and s1.product_id = s2.product_id;
There may be a simpler way to do this using a join, but this should work.
Let's suppose table Product has a primary key ProdID, and table Sold a foreign key into Product by the same name as well as a Customer field (probably another foreign key into a third table Customer, but since you say there must be only two tables we'll assume a string that's the customer name, instead). Then:
Select DISTINCT Product.ProdID
From Product
Inner Join Sold SA On (Product.ProdID=SA.ProdID
AND SA.Customer='A')
Inner Join Sold SB On (Product.ProdID=SB.ProdID
AND SB.Customer='B')
will give you the ProdID in question (of course, you can get other columns from that table, too, we just have no idea what those columns might be;-).