Converting JOIN to Subquery - sql-server

I am trying to figure out how to convert a JOIN to a subquery. I am using AdventureWorks2019 database and I am pulling data from two tables. My JOIN statement I created is:
SELECT FirstName, MiddleName, LastName, StateProvinceID
FROM Person.Person AS P
JOIN Person.BusinessEntityAddress AS BEA
ON P.BusinessEntityID = BEA.AddressID
JOIN Person.Address AS A
ON BEA.BusinessEntityID = A.AddressID
WHERE StateProvinceID = 79;
How do I turn this into a subquery? Do I create them in FROM or WHERE?

Related

How to insert keys from one database to another?

Here is my code for inserting values from AdventureWorks to custom database.
I needed to transfer identifiers from AdventureWorks too but copy of identifiers are not allowed. So I thought using distinct with identifier would be enough, but I still get error about inserting duplicates.
If you could comment and tell me what I am doing wrong I would be very grateful.
Thank you!
Here is my full attempt: https://pastebin.com/ZPniteh1
set identity_insert proizvodi ON
insert into proizvodi (ProizvodID, Sifra, Naziv, Kategorija, Podkategorija, Boja, Cijena, StanjeZaliha)
select distinct
p.ProductID, p.ProductNumber,p.[Name], pc.[Name],psc.[Name],
p.Color, p.ListPrice, pii.Quantity
from
AdventureWorks2017.Production.Product as p
join
AdventureWorks2017.Production.ProductSubcategory as psc on psc.ProductSubcategoryID = p.ProductSubcategoryID
join
AdventureWorks2017.Production.ProductCategory as pc on pc.ProductCategoryID = psc.ProductCategoryID
inner join
AdventureWorks2017.Production.ProductInventory as pii on pii.ProductID = p.ProductID
inner join
AdventureWorks2017.Sales.SalesOrderDetail as sod on sod.ProductID = p.ProductID
inner join
AdventureWorks2017.Sales.SalesOrderHeader as soh on soh.SalesOrderID = sod.SalesOrderID
inner join
AdventureWorks2017.Sales.SalesTerritory as st on st.TerritoryID = soh.TerritoryID
inner join
AdventureWorks2017.Production.[Location] as l on l.LocationID = pii.LocationID
where
st.[Group] ='Europe'
order by
p.ProductID
set identity_insert proizvodi OFF

Select all the data from another table even if corresponding value from another table is NULL

I have this query:
SELECT city.CITY_NAME,
SUM(case when c.CUSTOMER_ID=o.CUSTOMER_ID and o.ORDER_ID=od.ORDER_ID
then od.TOTAL_AMT_PER_ITEM
else 0 end) AS TOTAL_AMT_PER_ITEM
FROM [ORDER] o
INNER JOIN ORDER_DETAILS od
ON o.ORDER_ID = od.ORDER_ID
INNER JOIN CUSTOMER c
ON o.CUSTOMER_ID = c.CUSTOMER_ID
INNER JOIN CUSTOMER_ADDRESS ca
ON ca.CUSTOMER_ID = c.CUSTOMER_ID
INNER JOIN CITY city
ON ca.CITY_ID = city.CITY_ID
GROUP BY city.CITY_NAME
I am a beginner in SQL SERVER. This query displays only the CITY_NAME that has a corresponding TOTAL_AMT_PER_ITEM value. What I need is to display all the CITY_NAMEs in the database even if their corresponding value is NULL. What is the work around for this? Can someone help me out? Thanks!
I change the order of the joins maybe that help.
You start with CITY because is the source for your GROUP BY and try to see if have any CUSTOMER_ADDRESS.
I guess if is a new store you can have 0 customers.
Then INNER JOIN because direction cant exist alone, they belong to a customer
Then LEFT JOIN because again a CUSTOMER may or may not have [ORDERS].
Then INNER JOIN because every [ORDERS] have [ORDER DETAILS]
Finally you SUM(od.TOTAL_AMT_PER_ITEM) from the last JOIN table, this can get some NULL's so you need include COALESCE
SELECT city.CITY_NAME,
COALESCE(SUM(od.TOTAL_AMT_PER_ITEM) , 0) as TOTAL_AMT_PER_ITEM
FROM [CITY]
LEFT JOIN [CUSTOMER_ADDRESS] ca
ON ca.CITY_ID = [CITY].CITY_ID
INNER JOIN CUSTOMER c
ON ca.CUSTOMER_ID = c.CUSTOMER_ID
LEFT JOIN [ORDER] o
ON o.CUSTOMER_ID = c.CUSTOMER_ID
INNER JOIN ORDER_DETAILS od
ON o.ORDER_ID = od.ORDER_ID
GROUP BY [CITY].CITY_NAME
btw you should change the name of the table [Order] to [Orders] because Order is a reserved word and can cause problems.
In general I rather use the plural name for tables because is an entity saving multiple of one type
CITIES instead of CITY
CUSTOMERS intead of CUSTOMER
ORDER_DETAILS is already plural, so try to keep consistence.
SELECT
city.CITY_NAME,
SUM(od.TOTAL_AMT_PER_ITEM) AS TOTAL_AMT_PER_ITEM
FROM
CUSTOMER c
INNER JOIN
CUSTOMER_ADDRESS ca
ON ca.CUSTOMER_ID = c.CUSTOMER_ID
INNER JOIN
CITY city
ON ca.CITY_ID = city.CITY_ID
LEFT JOIN
[ORDER] o
ON o.CUSTOMER_ID = c.CUSTOMER_ID
LEFT JOIN
ORDER_DETAILS
ON o.ORDER_ID = od.ORDER_ID
GROUP BY city.CITY_NAME

Inserting into new Table getting more records, CROSS JOIN, UPDATE

In my current data structure my OFFENSE table doesnt have all the columns that I need. For this reason I inner join it with several other table columns and insert it into a new table called TexasCCHPublicRecords created by me. This is my query:
INSERT INTO TexasCCHPublicRecords (OFF_IDN, TRS_IDN, AGY_TXT, DOO_DTE, AON_COD, AOL_TXT, LDA_CODE, GOC_COD, ADN_COD, ADD_TXT, ADA_DTE, REF_TXT,
IPN_NBR, ICA_NBR, DMV_COD, TRS_CODE, TRN_CODE, PERSON_ID, FIRST_NAME, LAST_NAME, DATE_OF_BIRTH, CDN, OffenseCode, OffenseName, CDNCode, ArrestingAgency,
ArrestingAgencyORI, ProsecutionAgency, ProsecutionAgencyORI)
SELECT o.* , trs.TRS_COD as 'TRS_CODE', trn.TRN_NBR as 'TRN_CODE', p.PER_IDN as 'PERSON_ID', nam.FNA_TXT as 'FIRST_NAME', nam.LNA_TXT as 'LAST_NAME',
birth.DOB_DTE as 'DATE_OF_BIRTH', cdnCode.CDN_VAL_TXT as 'CDN', offenseCode.OFF_COD as 'OffenseCode', offenseCode.LIT_TXT as 'OffenseName',
cdnCode.CDN_VAL_COD as 'CDNCode', arrestingAgency.ATR_TXT as 'ArrestingAgency', arrestingAgency.ORI_TXT as 'ArrestingAgencyORI',
prosecutionAgency.ATR_TXT as 'ProsecutionAgency',prosecutionAgency.ORI_TXT as 'ProsecutionAgencyORI'
FROM OFFENSE o
inner join CCH_PUBLIC.dbo.TRS trs on trs.TRS_IDN = o.TRS_IDN
inner join CCH_PUBLIC.dbo.TRN trn on trn.TRN_IDN = trs.TRN_IDN
inner join CCH_PUBLIC.dbo.PERSON p on p.IND_IDN = trn .IND_IDN
inner join CCH_PUBLIC.dbo.NAME nam on nam.PER_IDN = p.PER_IDN
inner join CCH_PUBLIC.dbo.BRTHDATE birth on birth.PER_IDN = p.PER_IDN
inner join CCH_PUBLIC.dbo.PROSECUTION prose on prose.TRS_IDN = o.TRS_IDN
inner join CCH_PUBLIC.dbo.AGENCY arrestingAgency on arrestingAgency.ORI_TXT = o.AGY_TXT
inner join CCH_PUBLIC.dbo.AGENCY prosecutionAgency on prosecutionAgency.ORI_TXT = o.REF_TXT
inner join CCH_PUBLIC.dbo.CRT_STAT crtStat on crtStat.TRS_IDN = o.TRS_IDN
inner join CCH_PUBLIC.dbo.CDN_COD cdnCode on cdnCode.CDN_VAL_COD = crtStat.CDN_COD
inner join CCH_PUBLIC.dbo.OFF_CODE offenseCode on offenseCode.OFF_COD = o.AON_COD
I would conclude that this table would select every offense in the OFFENSE table inner join it with the other tables and insert it into the TexasCCHPublicRecords
However after running this simple count
select count(*) as 'Offense Table Record Count' FROM OFFENSE
select count(*) as 'CCHPublicRecords Table Record Count' FROM TexasCCHPublicRecords
I end with these results:
Offense Table Record Count
11372377
CCHPublicRecords Table Record Count
49666836
There are 38 million more records in my new table. How did this happen? Is my query inserting repeated instances of the same offense row?
My goal is to SELECT an OFFENSE inner join it with the tables that are associated with it and INSERT that into my empty table. What am i doing wrong?
UPDATE
After reading one of the comments I realized that one of the tables was giving me 7 columns. Now I am trying to ONLY select the FIRST result. I am trying to do a CROSS APPLY however I am not sure what to place on the outside of the cross apply. This is my select Query:
SELECT o.*, trs.TRS_COD as 'TRS_CODE', trn.TRN_NBR as 'TRN_CODE', p.PER_IDN as 'PERSON_ID', nam.FNA_TXT as 'FIRST_NAME', nam.LNA_TXT as 'LAST_NAME',
birth.DOB_DTE as 'DATE_OF_BIRTH', cdnCode.CDN_VAL_TXT as 'CDN', offenseCode.OFF_COD as 'OffenseCode', offenseCode.LIT_TXT as 'OffenseName',
cdnCode.CDN_VAL_COD as 'CDNCode', arrestingAgency.ATR_TXT as 'ArrestingAgency', arrestingAgency.ORI_TXT as 'ArrestingAgencyORI',
prosecutionAgency.ATR_TXT as 'ProsecutionAgency',prosecutionAgency.ORI_TXT as 'ProsecutionAgencyORI'
FROM OFFENSE o
inner join CCH_PUBLIC.dbo.TRS trs on trs.TRS_IDN = o.TRS_IDN
inner join CCH_PUBLIC.dbo.TRN trn on trn.TRN_IDN = trs.TRN_IDN
inner join CCH_PUBLIC.dbo.PERSON p on p.IND_IDN = trn.IND_IDN
inner join CCH_PUBLIC.dbo.BRTHDATE birth on birth.PER_IDN = p.PER_IDN
inner join CCH_PUBLIC.dbo.PROSECUTION prose on prose.TRS_IDN = o.TRS_IDN
inner join CCH_PUBLIC.dbo.AGENCY arrestingAgency on arrestingAgency.ORI_TXT = o.AGY_TXT
inner join CCH_PUBLIC.dbo.AGENCY prosecutionAgency on prosecutionAgency.ORI_TXT = o.REF_TXT
inner join CCH_PUBLIC.dbo.CRT_STAT crtStat on crtStat.TRS_IDN = o.TRS_IDN
inner join CCH_PUBLIC.dbo.CDN_COD cdnCode on cdnCode.CDN_VAL_COD = crtStat.CDN_COD
inner join CCH_PUBLIC.dbo.OFF_CODE offenseCode on offenseCode.OFF_COD = o.AON_COD
CROSS APPLY (
SELECT TOP 1 *
FROM CCH_PUBLIC.dbo.NAME as nam
WHERE nam.PER_IDN = p.PER_IDN
) nam
is the nam out of the CROSS APPLY correct?

How to get values from 3 tables?

CREATE PROCEDURE spJoin3Tables
AS
BEGIN
SELECT
tbl_Jobs.JobTitle, tbl_Company.CompName
FROM
tbl_Jobs
INNER JOIN
tbl_Company ON tbl_Jobs.CompID = tbl_Company.ID
SELECT
tbl_Cities.CityName
FROM
tbl_Cities
INNER JOIN
tbl_JobCities ON tbl_Cities.ID = tbl_JobCities.CityID
INNER JOIN
tbl_Jobs ON tbl_JobCities.JobID = tbl_Jobs.ID
END
The result is two tables. I want to get all three columns in one table - what will be the query?
You just need to add the company table and the columns from the first query to the second query and make sure to join on the company id.
SELECT
tbl_Cities.CityName, tbl_Jobs.JobTitle, tbl_Company.CompName
FROM
tbl_Cities
INNER JOIN
tbl_JobCities ON tbl_Cities.ID = tbl_JobCities.CityID
INNER JOIN
tbl_Jobs ON tbl_JobCities.JobID = tbl_Jobs.ID
INNER JOIN
tbl_Company ON tbl_Jobs.CompID = tbl_Company.ID
USING INNER JOIN U CAN GET ALL DATE. IF IN CASE ANY TABLE IN ID COLUMNS NULL VALUE THEN USER LEFT JOIN
SELECT tbl_Jobs.JobTitle, tbl_Company.CompName , tbl_Cities.CityName
FROM tbl_Jobs
INNER JOIN tbl_Company ON tbl_Jobs.CompID = tbl_Company.ID
INNER JOIN tbl_JobCities ON tbl_JobCities.JobID = tbl_Jobs.ID
INNER JOIN tbl_Cities ON tbl_Cities.ID = tbl_JobCities.CityID

Use String Row As column

I have UserExams tables shown below
I need to display like FirstName, First, Second, Final
I've tried using PIVOT but the aggregation function don't return all StudentMarks
select *
from
(
SELECT Users.FirstName,
ExamsNames.Name,
UserExams.StudentMark
FROM Exams INNER JOIN ExamsNames ON Exams.ExamNameID = ExamsNames.ExamsNamesID
INNER JOIN UserExams ON Exams.ExamID = UserExams.ExamID
INNER JOIN Users ON UserExams.UserID = Users.UserID
)t
PIVOT
(
min(StudentMark)
for Name in ([First],[Second],[Final])
)p
The way your current query is written you are going to return one min(StudentMark) for each exam in Name. If you want to return multiple values for each exam, then you will want to include another column that will give you distinct rows - I would suggest using row_number:
select FirstName, [First],[Second],[Final]
from
(
SELECT Users.FirstName,
ExamsNames.Name,
UserExams.StudentMark,
row_number() over(partition by Users.FirstName, ExamsNames.Name
order by UserExams.StudentMark) seq
FROM Exams
INNER JOIN ExamsNames ON Exams.ExamNameID = ExamsNames.ExamsNamesID
INNER JOIN UserExams ON Exams.ExamID = UserExams.ExamID
INNER JOIN Users ON UserExams.UserID = Users.UserID
)t
PIVOT
(
min(StudentMark)
for Name in ([First],[Second],[Final])
)p

Resources