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
Related
I am trying to bring this query in Snowflake. But, getting huge numbers with the last 3 inner joins which has same tables with different conditions.
select count(*) from table2; --5
select count(*) from table_3;--2824134
select count(*) from table1;--478015
Original Query:
select * from
from table1 d_tbl
inner join table2 r on r.number = d_tbl.number
inner join table_3 Zero on Zero.ID_I = r.id and Zero.time <= d_tbl.starttime and Zero.typeid in (7,19)
inner join table_3 first on first.ID_I = r.id and first.time <= Zero.time and first.typeid in (8,9)
inner join table_3 second on second.ID_I = r.id and second.time >= d_tbl.endtime and second.typeid in (8,9)
where d_tbl.mode = 0;
I tried breaking the queries into 3 parts.
create temp table tb1 as
select *
from table1 d_tbl
inner join table2 r on r.number = d_tbl.number ;
create temp table tb2 as
select ID_I , time as time as Zero_time,time as first_time,time as second_time
from table_3
where typeid in (8,9,7,19)
Note: saving the time column with different names for reference.
create temp table final_table as
select * from tb1 r
inner join tb2
on tb2.ID_I = r.id
where tb2.Zero_time <= r.starttime
and tb2.first_time <= Zero.time
and tb2.second_time >= r.endtime
Basically, I am trying to break the conditions in the joins to different parts.
This same logic has to be applied for different tables and do a union all for final table values.
Please help if this would work or let me know if this shall be handled with a better approach that executes faster.
TIA.
Try and convert following -
select * from
from table1 d_tbl
inner join table2 r on r.number = d_tbl.number
inner join table_3 Zero on Zero.ID_I = r.id
AND Zero.time <= d_tbl.starttime and Zero.typeid in (7,19)
inner join table_3 first on first.ID_I = r.id
AND first.time <= Zero.time and first.typeid in (8,9)
inner join table_3 second on second.ID_I = r.id
AND second.time >= d_tbl.endtime and second.typeid in (8,9)
where d_tbl.mode = 0;
To something like below -
select whatever-columns,
case when t3.time <= d_tbl.starttime
AND Zero.typeid in (7,19) then t3.time_1 end as zero_time,
case when t3.time <= zero_time
AND Zero.typeid in (8,9) then t3.time_1 end as first_time, --- snowflake allows to select/reference previous column
case when t3.time >= d_tbl.endtime
AND second.typeid in (8,9)then t3.time_1 end as second_time
from
table1 d_tbl
inner join table2 r on r.number = d_tbl.number
inner join table_3 t3 on t3.ID_I = r.id
where d_tbl.mode = 0;
This will help to reduce data-set being searched by avoiding multiple inner join on same table that has most records.
I have a query and a diag_code is either in one table (UM_SERVICE) or the other (LOS), but I can't join both tables to get diag_code that isn't null, that I can think of. Does this look ok for finding if diag_code is in one of the tables and lookup table? It's possible to have both LOS and UM_SERVICE have a diag code on different rows, and they could be different, and both or one could be in the lookup table. I'm not seeing anything in internet search.
Here's a simplified stored procedure:
SELECT distinct
c.id
,uc.id
,c.person_id
FROM dbo.CASES c
INNER JOIN dbo.UM_CASE uc with (NOLOCK) ON uc.case_id = c.id
LEFT JOIN dbo.UM_SERVICE sv (NOLOCK) ON sv.case_id = omc.case_id
LEFT JOIN dbo.UM_SERVICE_CERT usc on usc.service_id = sv.id
LEFT JOIN dbo.LOS S WITH (NOLOCK) ON S.case_id = UC.case_id
LEFT JOIN dbo.LOS_EXTENSION SC WITH (NOLOCK) ON SC.los_id = S.id
INNER JOIN dbo.PERSON op with (NOLOCK) on op.id = c.Person_id
WHERE
(sv.diag_code is not null and c.case_id = sv.case_id
or
s.diag_code is not null and c.case_id = s.case_id)
and
(sv.diag_code is not null and sv.diag_code in (select diag_code from TABLE_LOOKUP)
or
s.diag_code is not null and s.diag_code in (select diag_code from TABLE_LOOKUP)
Table setups like this:
CASES
id person_id
UM_CASE
case_id
LOS
case_id id
LOS_EXTENSION
los_id
Person
id cid
UM_SERVICE
case_id diag_code
UM_SERVICE_CERT
service_id id
TABLE_LOOKUP
diag_code
Since you have two different searches being run, it is going to be much easier to write/read by writing the searches individually and then bringing your two results sets together using the UNION operator. The UNION will eliminate duplicates across the two result sets in a similar manner to what your usage of SELECT DISTINCT is doing for a single result set.
Like so:
/*first part of union performs seach using filter on dbo.UM_SERVICE*/
SELECT
c.id
,uc.id
,c.person_id
FROM
dbo.CASES AS c
INNER JOIN dbo.UM_CASE AS uc ON uc.case_id=c.id
LEFT JOIN dbo.UM_SERVICE AS sv ON sv.case_id = omc.case_id
LEFT JOIN dbo.UM_SERVICE_CERT AS usc on usc.service_id=sv.id
LEFT JOIN dbo.LOS AS S ON S.case_id = UC.case_id
LEFT JOIN dbo.LOS_EXTENSION AS SC ON SC.los_id= S.id
INNER JOIN dbo.PERSON AS op on op.id=c.Person_id
WHERE
sv.diag_code in (select diag_code from TABLE_LOOKUP) /*will eliminate null values in sv.diag_code*/
UNION /*deduplicate result sets*/
/*second part of union performs search using filter on dbo.LOS*/
SELECT
c.id
,uc.id
,c.person_id
FROM
dbo.CASES AS c
INNER JOIN dbo.UM_CASE AS uc ON uc.case_id=c.id
LEFT JOIN dbo.UM_SERVICE AS sv ON sv.case_id = omc.case_id
LEFT JOIN dbo.UM_SERVICE_CERT AS usc on usc.service_id=sv.id
LEFT JOIN dbo.LOS AS S ON S.case_id = UC.case_id
LEFT JOIN dbo.LOS_EXTENSION AS SC ON SC.los_id= S.id
INNER JOIN dbo.PERSON AS op on op.id=c.Person_id
WHERE
s.diag_code in (select diag_code from TABLE_LOOKUP); /*will eliminate null values in s.diag_code*/
I have difficulty joining two tables that look like the following:
The main table PMEOBJECT which has a unique key named OBJECTID and
has in total 12768 rows.
Then I want to join PMEOBJECTVALIDITY on it which has an n:1 relationship with PMEOBJECT, since it has more rows,
because it saves the changes over time of PMEOBJECT (i.e. when a certain object is not
valid anymore), this one has 12789 rows (meaning only 21 objects
changed over time). However, I only want to have the current last
VALIDFROM date shown in the query. This all works fine.
Then the trouble starts when I want to join PMEOBJECTDIMENSION, which has an
n:1 relationship with PMEOBJECTVALIDITY and has 36737 rows in total.
SELECT
PMEOBJECT.OBJECTID
,PMEOBJECTVALIDITY.VALIDFROM
,PMEOBJECTDIMENSION.DIMENSION2_
FROM PMEOBJECT
LEFT JOIN PMEOBJECTVALIDITY
ON PMEOBJECTVALIDITY.OBJECTID = PMEOBJECT.OBJECTID
AND PMEOBJECTVALIDITY.DATAAREAID = PMEOBJECT.DATAAREAID
INNER JOIN(
SELECT
OBJECTID,
MAX(VALIDFROM) AS NEWFROMDATE,
MAX(VALIDTO) AS NEWTODATE
FROM PMEOBJECTVALIDITY B
GROUP BY OBJECTID
) B
ON PMEOBJECTVALIDITY.OBJECTID = B.OBJECTID
AND PMEOBJECTVALIDITY.VALIDFROM = B.NEWFROMDATE
LEFT JOIN PMEOBJECTDIMENSION
ON PMEOBJECTDIMENSION.OBJECTVALIDITYID = PMEOBJECTVALIDITY.RECID
AND PMEOBJECTDIMENSION.DATAAREAID = PMEOBJECTVALIDITY.DATAAREAID
INNER JOIN(
SELECT
OBJECTVALIDITYID,
MAX(VALIDFROM) AS NEWFROMDATE_2
FROM PMEOBJECTDIMENSION C
GROUP BY OBJECTVALIDITYID
) C
ON PMEOBJECTDIMENSION.OBJECTVALIDITYID = C.OBJECTVALIDITYID
AND PMEOBJECTDIMENSION.VALIDFROM = C.NEWFROMDATE_2
Results in query per step:
SELECT PMEOBJECT: 12768 rows
LEFT JOIN PMEVALIDITY: 12789 rows
INNER JOIN PMEVALIDITY: 12768 rows
LEFT JOIN PMEOBJECTDIMENSION: 36737 rows
INNER JOIN PMEOBJECTDIMENSION: 12729 rows
I want the end result again to have the same 12768 rows, I don't want any ObjectId to be left out.
What am I missing here?
Kind regards,
Igor
Following might help:
from PMEOBJECTDIMENSION onwards:
LEFT JOIN (SELECT PMEOBJECTDIMENSION.OBJECTVALIDITYID, PMEOBJECTDIMENSION.DATAAREAID
FROM PMEOBJECTDIMENSION
INNER JOIN(SELECT OBJECTVALIDITYID, MAX(VALIDFROM) AS NEWFROMDATE_2
FROM PMEOBJECTDIMENSION C
GROUP BY OBJECTVALIDITYID
) C
ON PMEOBJECTDIMENSION.OBJECTVALIDITYID = C.OBJECTVALIDITYID
AND PMEOBJECTDIMENSION.VALIDFROM = C.NEWFROMDATE_2
)X
ON X.OBJECTVALIDITYID = PMEOBJECTVALIDITY.RECID
AND X.DATAAREAID = PMEOBJECTVALIDITY.DATAAREAID
and select the distinct records if duplicates present.
The INNER JOINs are filtering out records- what you want is that the LEFT JOIN table (PMEOBJECTVALIDITY and PMEOBJECTDIMENSION) should only include records that have at least a match on the INNER JOIN queries (alias B and C). You can accomplish this with by nesting the INNER JOIN with the LEFT JOIN, generally done as follows:
SELECT *
FROM A
LEFT JOIN B
INNER JOIN C
ON B.ID = C.BID
ON A.ID = B.AID
Now B is INNER JOINed on C and will only contain records that have a match in C, but will preserve the LEFT JOIN not remove any records from A.
In your case, you can simply move the ON clause from the LEFT JOIN to the end of the following INNER JOIN.
SELECT
PMEOBJECT.OBJECTID
,PMEOBJECTVALIDITY.VALIDFROM
,PMEOBJECTDIMENSION.DIMENSION2_
FROM PMEOBJECT
LEFT JOIN PMEOBJECTVALIDITY
INNER JOIN(
SELECT
OBJECTID,
MAX(VALIDFROM) AS NEWFROMDATE,
MAX(VALIDTO) AS NEWTODATE
FROM PMEOBJECTVALIDITY B
GROUP BY OBJECTID
) B
ON PMEOBJECTVALIDITY.OBJECTID = B.OBJECTID
AND PMEOBJECTVALIDITY.VALIDFROM = B.NEWFROMDATE
ON PMEOBJECTVALIDITY.OBJECTID = PMEOBJECT.OBJECTID
AND PMEOBJECTVALIDITY.DATAAREAID = PMEOBJECT.DATAAREAID --here it is!
LEFT JOIN PMEOBJECTDIMENSION
INNER JOIN(
SELECT
OBJECTVALIDITYID,
MAX(VALIDFROM) AS NEWFROMDATE_2
FROM PMEOBJECTDIMENSION C
GROUP BY OBJECTVALIDITYID
) C
ON PMEOBJECTDIMENSION.OBJECTVALIDITYID = C.OBJECTVALIDITYID
AND PMEOBJECTDIMENSION.VALIDFROM = C.NEWFROMDATE_2
ON PMEOBJECTDIMENSION.OBJECTVALIDITYID = PMEOBJECTVALIDITY.RECID
AND PMEOBJECTDIMENSION.DATAAREAID = PMEOBJECTVALIDITY.DATAAREAID --I'm here
I have a query which joins 3,4 tables(like select * from table1 join table2 join table3) and the same query is used in my stored procedure multiple time. Is there any way to keep that query in one place and i can use it in my entire stored procedure(with in a single stored procedure)?
SELECT p.PK_PatientID
FROM Patients p
INNER JOIN PT ON e.FK_PatientID = p.PK_PatientID
INNER JOIN PN n ON n.FK_PatientEncounterID = e.PK_PatientEncounterID
INNER JOIN BP ep ON ep.FK_PatientEncounterID = e.PK_PatientEncounterID
INNER JOIN SOP pd ON ep.FK_SharedProcedureDetailID = pd.PK_SharedOfficeProcedureDetailID
INNER JOIN CQM vs ON pd.FK_SharedProcedureCode = vs.Code
This is the query i want to use it in my procedure multiple time
You could use Temp table or Table variable and insert data into it,if you are using the query multiple times
If you don't want to use temp tables or tables variables for reasons unknown,you could use a view
You can store your select query in a view:
CREATE VIEW vW_Example
AS
SELECT p.PK_PatientID
FROM Patients p
INNER JOIN PT ON e.FK_PatientID = p.PK_PatientID
INNER JOIN PN n ON n.FK_PatientEncounterID = e.PK_PatientEncounterID
INNER JOIN BP ep ON ep.FK_PatientEncounterID = e.PK_PatientEncounterID
INNER JOIN SOP pd ON ep.FK_SharedProcedureDetailID = pd.PK_SharedOfficeProcedureDetailID
INNER JOIN CQM vs ON pd.FK_SharedProcedureCode = vs.Code
Then you can call the view like this:
SELECT * FROM vW_Example
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?