UPDATE with SELECT with a reference to the updated table - sql-server

I have a script:
UPDATE a
SET fieldX =
(SELECT F_Aggregate(x.fieldy)
FROM table_B
INNER JOIN ....
INNER JOIN ....
INNER JOIN ....
....
INNER JOIN table_C on .....
WHERE table_C.fieldY = table_A.fieldY)
FROM table_A a;
But now I want to update fieldX only when the select gives a different value. Like:
UPDATE a
SET fieldX =
(SELECT dbo.F_Aggregate(x.fieldy) as result
FROM table_B
INNER JOIN ....
INNER JOIN ....
INNER JOIN ....
....
INNER JOIN table_C on .....
WHERE table_C.fieldY = table_A.fieldY)
FROM table_A a
WHERE fieldX <> result;
I have found questions/answers that looks like this but they all have a select statement without a reference to the updated table.
Does anybody know a solution?

Move the calculation in other Data Source - it could be CTE, table variable or temporary table, etc. Then join the updated table with it:
WITH DataSource (fieldY, result) AS
(
SELECT table_C.fieldY
,dbo.F_Aggregate(x.fieldy) as result
FROM table_B
INNER JOIN ....
INNER JOIN ....
INNER JOIN ....
....
INNER JOIN table_C on .....
GROUP BY table_C.fieldY
)
UPDATE table_A
SET fieldX = result
FROM table_A A
INNER JOIN DataSource DS
ON A.[fieldY] = DS.[fieldY]
WHERE fieldX <> result

Related

SQL Server 2005 Select Data From Table1 and Table2 but if Table2 column1 value is null Select Data From Table3

My Query IS
SELECT TblPharmacyBillingDetails.UPBNo, TblMasterBillingData.IPDNo, InPatRegistration.PatTitle+PatientName, TblPharmacyBillingDetails.InvoiceNo, TblPharmacyBillingDetails.InvoiceDateTime, TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
INNER JOIN InPatRegistration ON TblMasterBillingData.IPDNo = InPatRegistration.IPDNo
but if TblMasterBillingData.IPDNo value is NULL select Data From TblMasterBillingData.OPDNo and
INNER JOIN OutPatRegistration ON TblMasterBillingData.OPDNo = OutPatRegistration.IPDNo
Method #1: Using UNION
SELECT * FROm
(
SELECT TblPharmacyBillingDetails.UPBNo,
TblMasterBillingData.IPDNo,
InPatRegistration.PatTitle+PatientName,
TblPharmacyBillingDetails.InvoiceNo,
TblPharmacyBillingDetails.InvoiceDateTime,
TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
INNER JOIN InPatRegistration ON TblMasterBillingData.IPDNo = InPatRegistration.IPDNo
WHERE TblMasterBillingData.IPDNo IS NOT NULL
UNION ALL
SELECT TblPharmacyBillingDetails.UPBNo,
TblMasterBillingData.OPDNo,
OutPatRegistration .PatTitle + PatientName,
TblPharmacyBillingDetails.InvoiceNo,
TblPharmacyBillingDetails.InvoiceDateTime,
TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
INNER JOIN OutPatRegistration ON TblMasterBillingData.OPDNo = OutPatRegistration.OPDNo
WHERE TblMasterBillingData.OPDNo IS NOT NULL
)Tmp
ORDER BY TblPharmacyBillingDetails.UPBNo
Method #2 Using ISNULL and LEFT JOIN
SELECT TblPharmacyBillingDetails.UPBNo,
ISNULL(TblMasterBillingData.IPDNo,TblMasterBillingData.OPDNo),
ISNULL(IP.PatTitle + IP.PatientName, OP.PatTitle + OP.PatientName),
TblPharmacyBillingDetails.InvoiceNo,
TblPharmacyBillingDetails.InvoiceDateTime,
TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
LEFT JOIN InPatRegistration IP ON TblMasterBillingData.IPDNo = IP.IPDNo
LEFT JOIN outPatRegistration OP ON TblMasterBillingData.OPDNo = OP.OPDNo
ORDER BY TblPharmacyBillingDetails.UPBNo
You can write either case statement or ISNULL() function as shown below in the demo query.
SELECT
Orders.OrderID,
Case when Customers1.CustomerName is null then Customers2.CustomerName else Customers1.CustomerName
end as CustomerName, --way 1
ISNULL(Customers1.CustomerName, Customers2.CustomerName) as Customer, --way 2
Orders.OrderDate
FROM Orders
INNER JOIN Customers1 ON Orders.CustomerID = Customers1.CustomerID
INNER JOIN Customers2 ON Orders.CustomerID = Customers2.CustomerID
-- where your condition here
-- order by your column name
You can also check whether data is available or not in the table and join the table accordingly using if exists as shown below.
if exists(select 1 from tablename where columnname = <your values>)

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 apply where condition in each inner join in SQL Server

I would like to apply conditions on each inner join like below
select *
from table1 table
inner join table2 t on t.column= table.column where condition
inner join table3 tb on tb.column = table.column where condition
But error is thrown on second where condition
Incorrect syntax near the keyword 'inner'.
Very new to joins in SQL Server. Any help please?
You need to put WHERE clauses at the end of the statement, but you can do this in an inner join like this:
select * from table1 table
inner join table2 t on t.column= table.column
and t.someColumn = 'SomeValue' --Here you can join on a condition
inner join table3 tb on tb.column = t.column
where <condition>
--Or...
select * from table1 table
inner join table2 t on t.column= table.column
inner join table3 tb on tb.column = t.column
where
t.column = 'blah'
and tb.column = 'blah2'
With an inner join all the conditions apply to the complete recordset. So you can just put them all in the where clause
select *
from table1 table
inner join table2 t on t.column= table.column
inner join table3 tb on tb.column = table.column
where condition1 and condition2
But for instance when using a left join the conditions only apply to the join itself. So you can use the on clause like this
select *
from table1 table
left join table2 t on t.column = table.column AND condition1
left join table3 tb on tb.column = table.column AND condition2
If you're looking to keep your main query clean, you can use a CTE to logically filter your table, away from your main query:
;with Employees as
(
select * from People where PersonType = 'Employee'
)
select * from ParkingSpots ps
join Employees e on ps.PersonID = e.PersonID

Use of CASE in a SQL query

I have a SQL query like this:
SELECT *
FROM table1
INNER JOIN table2 ON table1.key = table2.key
INNER JOIN table3 ON table1.var = table3.var
INNER JOIN table4 ON table1.field = table4.field
but I only want to include the table3 join if a variable has a certain value (iMarket=250 and above)
I'm trying to get this sort of condition working:
SELECT *
FROM table1
INNER JOIN table2 ON table1.key = table2.key
CASE
WHEN iMarket > 250
THEN INNER JOIN table3 ON table1.var = table3.var
END
INNER JOIN table4 on table1.field = table4.field
This is pseudo-code but it approximates to what I'm trying to do. Nothing works. Is there an easier way of doing it? I want to exclude this join because it always fails if that variable is below a certain value. Thank you all!
As easy to include condition in join on clause:
SELECT * from table1
INNER JOIN table2 on table1.key=table2.key
INNER JOIN table3 on iMarket>250 and table1.var=table3.var
INNER JOIN table4 on table1.field=table4.field
Remember than you should use outer joins if you need all values from other tables despite the fact that they are no matches for table3, perhaps you are looking for this behavior:
SELECT * from table1
INNER JOIN table2 on table1.key=table2.key
INNER JOIN table4 on table1.field=table4.field
left outer join --<--
table3 on iMarket>250 and table1.var=table3.var

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

Resources