SQL query has me stumped - sql-server

Here is my situation: I have two tables, table A has columns:
ID,
Name,
ClassYear,
Classmonth
ID is the primary key no duplicates.
Table b has these columns:
ID,
addresstype
addline1
addline2
country,
city,
state,
zip
ID is not unique in table B but it is how you link back to table A.
If you have more than one address e.g. Home, school then you have more than on record in table b.
My task is to select everyone from table A that has a class year that is >= 2019 and everyone that has a class year = 2018 as long as the class month is >=5
I got that no problem.
Where it gets confusing to me is now that I have this list of people from table A I need to query table b and I only want to pull those who have both a home and school address types and the addresses are identical e.g. line 1, line 2, country, city, state, zip are identical.
I would greatly appreciate some insight.

You could group by the address' details and count the number of distinct types it has:
SELECT *
FROM table1
WHERE id IN (SELECT id
FROM table2
WHERE addresstype IN ('home', 'school')
GROUP BY id, addline1, addline2, country, city, state, zip
HAVING COUNT(DISTINCT addresstype) = 2)

SELECT
DISTINCT
student.ID
, student.Name
, student.ClassYear
, student.ClassMonth
FROM
TableA AS student
INNER JOIN TableB AS homeAddress ON
student.ID = homeAddress.ID
AND homeAddress.addressType = 'Home'
INNER JOIN TableB AS schoolAddress ON
student.ID = schoolAddress.ID
AND schoolAddress.addressType = 'School'
AND homeAddress.line1 = schoolAddress.line1
AND homeAddress.line2 = schoolAddress.line2
AND homeAddress.country = schoolAddress.country
AND homeAddress.city = schoolAddress.city
AND homeAddress.state = schoolAddress.state
AND homeAddress.zip = schoolAddress.zip
WHERE
student.classYear >= 2019
OR (student.ClassYear = 2018 AND student.classMonth >= 5)
;

Related

SQL Server : how to union 3 tables with different number of rows

I have 3 tables with different data and I need to return one table that includes all 3 tables:
Customer
Contacts
Addresses
I want to get the data in only one table and one record with all details like CustomerNumber, Name, City, officeNumber...., like Union
SELECT CU.[Name]
FROM Customers CU
WHERE CustomerNumber = #CustomerId
AND IsDeleted = 0
SELECT AD.City, AD.Street
FROM [Addresses] AD
WHERE CustomerId = #CustomerId
AND IsDeleted = 0
SELECT CO.FullName, CO.OfficeNumber, CO.Email
FROM [Contacts] CO
WHERE CustomerId = #CustomerId
AND IsDeleted = 0
Result:
Number of rows doesn't matter for a union number of columns do.
What do you expect with a union?
I suppose you want you want all information (name address, contact) of customer having Id= #CustomerId
If I am right, you should make 2 join between the 3 tables using CustomerId as join clause
Edit:
https://www.db-fiddle.com/f/uGhtAZAVk64KzgThGekKk6/11
You need to JOIN the tables not UNION them. Please research SQL Server JOIN as there multiple types of joins you can do. In this case you're looking for an INNER JOIN this type of join will only return records when you have matching keys in all the tables. The key in your case is the customer id. You JOIN the tables ON customer id. Your query should look something like this:
SELECT CU.[Name], AD.City, AD.Street, CO.FullName, CO.OfficeNumber, CO.Email
FROM Customers CU
INNER JOIN [Addresses] AD
ON CU.CustomerNumber = AD.CustomerId
INNER JOIN [Contacts] CO
ON CO.CustomerId = CU.CustomerNumber
WHERE CU.CustomerNumber = #CustomerId

Retrieving borrower name based on borrowertype id from another table in SQL Server

I have two tables, Customer and RegisteredCustomer.
Customer table has the first and last name of customers including the family members stored against each Residentid.
The RegisteredCustomer has the CustomerType as 1 being primary and 2 being FamilyMembers.
I want to select both the primary and Familymember displayed side by side.
Select FirstName, LastName
from Customer
Inner Join RegisteredCustomers on Customer.Customerid = RegisteredCustomer.Customerid
and CustomerType = 1
How can I achieve it?
Thanks
Try it like this:
Select a.Customerid,FirstName, LastName,b.CustomerType from
(Select Customerid,FirstName, LastName from Customer) as a
left join
(select Customerid,cusdescription,CustomerType from RegisteredCustomers)as b
on a.Customerid = b.Customerid where CustomerType = 1
Hope it could help.

SELECT from multiple queries

I have this tables:
tblDiving(
diving_number int primary key
diving_club int
date_of_diving date)
tblDivingClub(
number int primary key not null check (number>0),
name char(30),
country char(30))
tblWorks_for(
diver_number int
club_number int
end_working_date date)
tblCountry(
name char(30) not null primary key)
I need to write a query to return a name of a country and the number of "Super club" in it.
a Super club is a club which have more than 25 working divers (tblWorks_for.end_working_date is null) or had more than 100 diving's in it(tblDiving) in the last year.
after I get the country and number of super club, I need to show only the country's that contains more than 2 super club.
I wrote this 2 queries:
select tblDivingClub.name,count(distinct tblWorks_for.diver_number) as number_of_guids
from tblWorks_for
inner join tblDivingClub on tblDivingClub.number = tblWorks_for.club_number,tblDiving
where tblWorks_for.end_working_date is null
group by tblDivingClub.name
select tblDivingClub.name, count(distinct tblDiving.diving_number) as number_of_divings
from tblDivingClub
inner join tblDiving on tblDivingClub.number = tblDiving.diving_club
WHERE tblDiving.date_of_diving <= DATEADD(year,-1, GETDATE())
group by tblDivingClub.name
But I don't know how do I continue.
Every query works separately, but how do I combine them and select from them?
It's university assignment and I'm not allowed to use views or temporary tables.
It's my first program so I'm not really sure what I'm doing:)
WITH CTE AS (
select tblDivingClub.name,count(distinct tblWorks_for.diver_number) as diving_number
from tblWorks_for
inner join tblDivingClub on tblDivingClub.number = tblWorks_for.club_number,tblDiving
where tblWorks_for.end_working_date is null
group by tblDivingClub.name
UNION ALL
select tblDivingClub.name, count(distinct tblDiving.diving_number) as diving_number
from tblDivingClub
inner join tblDiving on tblDivingClub.number = tblDiving.diving_club
WHERE tblDiving.date_of_diving <= DATEADD(year,-1, GETDATE())
group by tblDivingClub.name
)
SELECT * FROM CTE
You can combine the queries using a UNION ALL as long as there are the same number of columns in each query. You can then roll them into a Common Table Expression (CTE) and do a select from that.

Multiple rows in one

I know there are similar questions like mine but unfortunately I haven't found the corresponding solution to my problem.
First off here's a simplified overview of my tables:
Partner table: PartnerID, Name
Address table: PartnerID, Street, Postcode, City, ValidFrom
Contact table: PartnerID, TypID, TelNr, Email, ValidFrom
A partner can have one or more addresses as well as contact info. With the contact info a partner could have let's say 2 tel numbers, 1 mobile number and 1 email. In the table it would look like this:
PartnerID TypID TelNr Email ValidFrom
1 1 0041 / 044 - 2002020 01.01.2010
1 1 0041 / 044 - 2003030 01.01.2011
1 2 0041 / 079 - 7003030 01.04.2011
1 3 myemail#hotmail.com 01.06.2011
What I need in the end is, combining all tables for each partner, is like this:
PartnerID Name Street Postcode City TelNr Email
1 SomeGuy MostActualStreet MostActualPC MostActualCity MostActual Nr (either type 1 or 2) MostActual Email
Any help?
Here's some T-SQL that gets the answer I think you're looking for if by "Most Actual"
you mean "most recent":
WITH LatestAddress (PartnerID,Street,PostCode,City)
AS (
SELECT PartnerID,Street,PostCode,City
FROM [Address] a
WHERE ValidFrom = (
SELECT MAX(ValidFrom)
FROM [Address] aMax
WHERE aMax.PartnerID = a.PartnerID
)
)
SELECT p.PartnerID,p.Name,la.Street,la.PostCode,la.City
,(SELECT TOP 1 TelNr FROM Contact c WHERE c.PartnerID = p.PartnerID AND TelNr IS NOT NULL ORDER BY ValidFrom DESC) AS MostRecentTelNr
,(SELECT TOP 1 Email FROM Contact c WHERE c.PartnerID = p.PartnerID AND Email IS NOT NULL ORDER BY ValidFrom DESC) AS MostRecentEmail
FROM [Partner] p
LEFT OUTER JOIN LatestAddress la ON p.PartnerID = la.PartnerID
Breaking it down, this example used a common table expression (CTE) to get the latest address information for each Partner
WITH LatestAddress (PartnerID,Street,PostCode,City)
AS (
SELECT PartnerID,Street,PostCode,City
FROM [Address] a
WHERE ValidFrom = (
SELECT MAX(ValidFrom)
FROM [Address] aMax
WHERE aMax.PartnerID = a.PartnerID
)
)
I left-joined from the Partner table to the CTE, because I didn't want partners who don't have addresses to get left out of the results.
FROM [Partner] p
LEFT OUTER JOIN LatestAddress la ON p.PartnerID = la.PartnerID
In the SELECT statement, I selected columns from the Partner table, the CTE, and I wrote two subselects, one for the latest non-null telephone number for each partner, and one for the latest non-null email address for each partner. I was able to do this as a subselect because I knew I was returning a scalar value by selecting the TOP 1.
SELECT p.PartnerID,p.Name,la.Street,la.PostCode,la.City
,(SELECT TOP 1 TelNr FROM Contact c WHERE c.PartnerID = p.PartnerID AND TelNr IS NOT NULL ORDER BY ValidFrom DESC) AS MostRecentTelNr
,(SELECT TOP 1 Email FROM Contact c WHERE c.PartnerID = p.PartnerID AND Email IS NOT NULL ORDER BY ValidFrom DESC) AS MostRecentEmail
I would strongly recommend that you separate your Contact table into separate telephone number and email tables, each with their own ValidDate if you need to be able to keep old phone numbers and email addresses.
Check out my answer on another post which explains how to get the most actual information in a case like yours : Aggregate SQL Function to grab only the first from each group
PS : The DATE_FIELD would be ValidFrom in your case.

How can I split off one table into another table using TSQL script

I have this code so far:
DECLARE #AddressIDS TABLE
(
AddressID int
)
INSERT INTO Address(Street1, City, StateCode, ZipCode)
OUTPUT inserted.AddressID INTO #AddressIDS
SELECT Street1, City, StateCode, ZipCode
FROM Contact
Now I need to put the IDs in the #AddressIDS back into the AddressID of the Contact table.
This better describes what I'm trying to do in TSQL:
Assuming Street1 + City + StateCode + ZipCode is unique, or that multiple contacts can share the same AddressID, then you don't need to suss out the AddressID values in an intermediate step. You can just perform your insert into Address and then:
UPDATE c
SET AddressID = a.AddressID
FROM dbo.Contact AS c
INNER JOIN dbo.Address AS a
ON c.Street1 = a.Street1
AND c.City = a.City
AND c.StateCode = a.StateCode
AND c.ZipCode = a.ZipCode;

Resources