Need Combined SQL Query to Update 2 Tables - sql

I am having 2 tables. Table1 and Table2. I need to update these 2 tables based on some conditions.
The SQL select query from Table1 will return multiple records, let's
name it as SQLQuery1
From SQLQuery1 results returned I need to loop through each record and
execute another SQL query from Table2 which will return only 1
record, let's name it as SQLQuery2
Update Table1 and Table2 with the results returned from SQLQuery2.
Is there is a single query to combine the above operations?
If you need more information please let me know
UPDATE:
Following are the Sample Queries used,
SELECT E.Id,E.Name
from Employee E
where E.transdate > '2019-01-201 00:00:01' -- Multiple Results(SQLQuery1)
SELECT top 1 ED.Id,ED.balance
FROM EmployeeDetails ED
where ED.Name= #Name -- Single Results((SQLQuery2)
UPDATE Employee set IsProcessed=true
where Id=#Id
UPDATE EmployeeDetails set IsProcessed=true
where Id=#Id

I would use an UPDATE with an INNER JOIN. I have no idea if it's best practice at this point in time or whether there is a better way to do this but it works for the example I have created in dbfiddle.
Something like this:
UPDATE E
SET IsProcessed = 1
FROM Employee E
INNER JOIN EmployeeDetails ED ON E.Id = ED.Id
WHERE E.transdate >= '2019-01-20 00:00:01' AND ED.name = 'Martin'
UPDATE ED
SET IsProcessed = 1
FROM EmployeeDetails ED
INNER JOIN Employee E ON E.Id = ED.Id
WHERE E.transdate >= '2019-01-20 00:00:01' AND ED.name = 'Martin'
I used >= because I just set all 3 created records to the datetime you have and forgot that looking for a datetime greater than that would provide me with nothing. I also used a hard-coded name Martin instead of using a variable.
Here is my link to the dbfiddle I created in which I created Employee and EmployeeDetails, filled them with test data and then proceeded to identify the correct records using the date, time and name joined by their ID values:
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=4492b27a9790f34b0bff0996e7fb6d36

Use INNER JOIN :
update e
set e.IsProcessed = 1 -- assuming BIT type
from employee e inner join
EmployeeDetails ed
on ed.name = e.name and ed.id = e.id
where e.transdate > '2019-01-201 00:00:01';
update ed
set ed.IsProcessed = 1 -- assuming BIT type
from EmployeeDetails ed inner join
Employee e
on ed.name = e.name and ed.id = e.id and
where e.transdate > '2019-01-201 00:00:01';

I wouldn't do it like this.
You can use outer apply to get rid of the cursor:
SELECT *
FROM T_Query1
OUTER APPLY
(
SELECT TOP 1 * FROM T_Query2
WHERE T_Query2.query1_id = T_Query1.id
) AS tQuery2
Then you can do an update like this:
UPDATE A
SET some_value = tQuery2.some_new_value
FROM T_Query1 AS A
OUTER APPLY
(
SELECT TOP 1 * FROM T_Query2
WHERE T_Query2.query1_id = A.id
) AS tQuery2
Besides that, you cannot update 2 tables with one update statement, AFAIK.
Your best bet would be
;WITH CTE AS
(
SELECT T_Query1.field1, T_Query2.field2, T_Query2.newField1
FROM T_Query1
OUTER APPLY
(
SELECT TOP 1 * FROM T_Query2
WHERE T_Query2.query1_id = T_Query1.id
) AS tQuery2
)
-- SELECT * FROM CTE
UPDATE CTE SET field1 = newField1, field2 = newField1
but I don't think CTE updating can handle outer-apply.

Related

Foreach loop on two SQL tables

I have two tables which are totally independent from each other, and I need to extract information from both of them and generate a CSV.
I'm doing this query:
SELECT NOM_FLUX, TYPE_CONTENU, DATE_DEPOT_GED
FROM FLUX_GED
WHERE TYPE_CONTENU = 'TEMPO_COURRIER_FSS'
AND NOM_FLUX NOT LIKE 'PCC%'
With this result:
Then I'm doing a query from this result with the ID
Like This (on the first result)
SELECT ID, URL_RELATIVE, TYPE_CONTENU, NOM_ELEMENT
FROM ELEMENT_GED
WHERE ID IN (
SELECT ID_ELEMENT
FROM SUIVI_GED
WHERE ID_FLUX IN (18682403)
)
With this result:
And here is the information from the SUIVI_GED table:
First I would like to do like a PowerShell foreach loop on every ID of my first query and then export the result of both query in a common csv.
I would like a result like that for my csv:
NOM_FLUX;URL_RELATIVE;TYPE_CONTENU;NOM_ELEMENT
infoNomFlux;infoURL;infoType;infoNOM
You seem to want join. A rather literal translation of your queries would be:
select
f.nom_flux,
f.type_contenu as type_contenu_flux,
f.date_depot_ged ,
e.id,
e.url_relative,
e.type_contenu as type_contenu_element,
e.nom_element
from flux_ged f
inner join element_ged e
on exists (select 1 from suivi_ged s where s.id_flux = f.id and e.id = s.id)
where
f.type_contenu = 'TEMPO_COURRIER_FSS'
and f.nom_flux not like 'PCC%'
Depending on your actual design, you might be able to flatten the exists condition as another join:
select
f.nom_flux,
f.type_contenu as type_contenu_flux,
f.date_depot_ged ,
e.id,
e.url_relative,
e.type_contenu as type_contenu_element,
e.nom_element
from flux_ged f
inner join suivi_ged s on s.id_flux = f.id
inner join element_ged e on e.id = s.id
where
f.type_contenu = 'TEMPO_COURRIER_FSS'
and f.nom_flux not like 'PCC%'

In a stored procedure how can you loop table A and then update table B

Within a stored procedure I need to loop the following table:
SELECT *
FROM dbo.UsersInRoles
INNER JOIN Application_Users ON UsersInRoles.AppUserID = Application_Users.AppUserID
WHERE (UsersInRoles.ApplicationId = #ApplicationId)
AND (UsersInRoles.RoleId = #CurrentRoleId)
AND (Application_Users.LastLogin < #StartDate)
And for each record that is looped I need to perform this update:
UPDATE UsersInRoles
SET UsersInRoles.RoleId = #DenyRoleId
WHERE (UsersInRoles.ApplicationId = #ApplicationId)
AND (UsersInRoles.RoleId = #CurrentRoleId)
If there is a better way to perform this then I'm open to suggestions. Basically the 1st query does a filter based upon the INNER JOIN to determine which records need to be updated. Then those filtered records are looped and updated with a new RoleID.
Update with join:
UPDATE UIR
SET UIR.RoleId = #DenyRoleId
FROM UsersInRoles UIR
INNER JOIN Application_Users ON UIR.AppUserID = Application_Users.AppUserID
WHERE (UIR.ApplicationId = #ApplicationId)
AND (UIR.RoleId = #CurrentRoleId)
AND (Application_Users.LastLogin < #StartDate)
You can use a CTE to do the UPDATE:
;WITH ToUpdate AS (
SELECT uir.RoleId
FROM dbo.UsersInRoles AS uir
INNER JOIN Application_Users AS au
ON uir.AppUserID = au.AppUserID
WHERE (uir.ApplicationId = #ApplicationId) AND
(uir.RoleId = #CurrentRoleId) AND
(au.LastLogin < #StartDate)
)
UPDATE ToUpdate
SET RoleId = #DenyRoleId
So, you just type wrap the query in a CTE and then perform the UPDATE on the table returned by the CTE. The RoleId value will be propagated to the records of the actual table, UsersInRoles.

Display Y/N column if record found in detail table

I'm trying to create a query so that I can have a column show Y/N if a particular item was ordered for a group of orders. The item I'm looking for would be OLI.id = '538'.
So my results would be:
Order#, Customer#, FreightPaid
12345, 00112233, Y
12346, 00112233, N
I cannot figure out if I need to use a subquery or the where exists function ?
Here's my current query:
SELECT distinct
OrderID,
Accountuid as Customerno
FROM [SMILEWEB_live].[dbo].[OrderLog] OL
inner join Orderlog_item OLI on OLI.orderlogkey = OL.[key]
inner join Account A on A.uid = OL.Accountuid
where A.GroupId = 'X9955'
and OL.CreateDate >= GETDATE() - 60
I would suggest an exists clause instead of a join:
select ol.OrderID, ol.Accountuid as Customerno,
(case when exists (select 1
from Orderlog_item OLI join
Account A
on A.uid = OL.Accountuid
where OLI.orderlogkey = OL.[key] and A.GroupId = 'X9955'
)
then 1 else 0
end) as flag
from [SMILEWEB_live].[dbo].[OrderLog] OL
where OL.CreateDate >= GETDATE() - 60;
This prevents a couple of problems. First, duplicate rows which are caused when there are multiple matching rows (and select distinct add unnecessary overhead). Second, missing rows, which happen when you use inner join instead of an outer join.

Selecting data from two tables with sql query

I have 2 tables
Course ( ID Date Description Duration Meatier_ID Promotion_ID).
second table
Ensign( E_Id Meatier_Id Promotion_Id)
infarct i have an id based on that id i have to Select data from Ensign where id=Eng_Id then i need to select data from Course where Meatier_Id and Promotion_Id in table Course are equal to Meatier_Id and Promotion_Id to data selected in earlier query
can i do it using one S q l query thanks
Br
Sara
Your question is bit vague, But I gave it a try
--These two variables take the place for your 'Earlier Query' values
DECLARE #Meatier_ID INT = 100,
#Promotion_Id INT = 15
--The query
SELECT *
FROM Course AS C
INNER JOIN Ensign AS E ON C.ID = E.E_Id
WHERE C.Meatier_ID = #Meatier_ID
AND C.Promotion_Id = #Promotion_Id
Join the two tables together on Meater_ID and Promotion_ID. Then select those rows where Eng_Id is the id you are working with.
SELECT *
FROM Course c
INNER JOIN Ensign e
ON e.Meatier_ID = c.Meatier_ID
AND e.Promotion_ID = c.Promotion_ID
WHERE e.Eng_Id = <id value here>
EDIT:
The above should work for SQL Server. For derby, try:
SELECT *
FROM Course
INNER JOIN Ensign
ON Ensign.Meatier_ID = Course.Meatier_ID
AND Ensign.Promotion_ID = Course.Promotion_ID
WHERE Ensign.Eng_Id = <id value here>
select e.E_Id, e.Meatier_Id, e.Promotion_Id, c.ID, c.Date, c.Description, c.Duration from Ensign as e inner join course as c where e.Meatier_Id=c.Meatier_Id and e.Promotion_Id=c.Promotion_Id and e.E_Id=#Eng_Id

How can I delete using INNER JOIN with SQL Server?

I want to delete using INNER JOIN in SQL Server 2008.
But I get this error:
Msg 156, Level 15, State 1, Line 15
Incorrect syntax near the keyword 'INNER'.
My code:
DELETE
FROM WorkRecord2
INNER JOIN Employee
ON EmployeeRun=EmployeeNo
WHERE Company = '1'
AND Date = '2013-05-06'
You need to specify what table you are deleting from. Here is a version with an alias:
DELETE w
FROM WorkRecord2 w
INNER JOIN Employee e
ON EmployeeRun=EmployeeNo
WHERE Company = '1' AND Date = '2013-05-06'
Just add the name of the table between DELETE and FROM from where you want to delete records, because we have to specify the table to delete. Also remove the ORDER BY clause because there is nothing to order while deleting records.
So your final query should be like this:
DELETE WorkRecord2
FROM WorkRecord2
INNER JOIN Employee
ON EmployeeRun=EmployeeNo
WHERE Company = '1'
AND Date = '2013-05-06';
It is possible this will be helpful for you -
DELETE FROM dbo.WorkRecord2
WHERE EmployeeRun IN (
SELECT e.EmployeeNo
FROM dbo.Employee e
WHERE ...
)
Or try this -
DELETE FROM dbo.WorkRecord2
WHERE EXISTS(
SELECT 1
FROM dbo.Employee e
WHERE EmployeeRun = e.EmployeeNo
AND ....
)
Try this:
DELETE FROM WorkRecord2
FROM Employee
Where EmployeeRun=EmployeeNo
And Company = '1'
AND Date = '2013-05-06'
In SQL Server Management Studio I can easily create a SELECT query:
SELECT Contact.Naam_Contactpersoon, Bedrijf.BedrijfsNaam, Bedrijf.Adres, Bedrijf.Postcode
FROM Contact
INNER JOIN Bedrijf ON Bedrijf.IDBedrijf = Contact.IDbedrijf
I can execute it, and all my contacts are shown.
Now change the SELECT to a DELETE:
DELETE Contact
FROM Contact
INNER JOIN Bedrijf ON Bedrijf.IDBedrijf = Contact.IDbedrijf
All the records you saw in the SELECT statement will be removed.
You may even create a more difficult inner join with the same procedure, for example:
DELETE FROM Contact
INNER JOIN Bedrijf ON Bedrijf.IDBedrijf = Contact.IDbedrijf
INNER JOIN LoginBedrijf ON Bedrijf.IDLoginBedrijf = LoginBedrijf.IDLoginBedrijf
It should be:
DELETE zpost
FROM zpost
INNER JOIN zcomment ON (zpost.zpostid = zcomment.zpostid)
WHERE zcomment.icomment = "first"
Try this query:
DELETE WorkRecord2, Employee
FROM WorkRecord2
INNER JOIN Employee ON (tbl_name.EmployeeRun=tbl_name.EmployeeNo)
WHERE tbl_name.Company = '1'
AND tbl_name.Date = '2013-05-06';
You could even do a sub-query. Like this code below:
DELETE FROM users WHERE id IN(
SELECT user_id FROM Employee WHERE Company = '1' AND Date = '2013-05-06'
)
Another way is using CTE:
;WITH cte
AS (SELECT *
FROM workrecord2 w
WHERE EXISTS (SELECT 1
FROM employee e
WHERE employeerun = employeeno
AND company = '1'
AND date = '2013-05-06'))
DELETE FROM cte
Note: We cannot use JOIN inside CTE when you want to delete.
Here's what I currently use for deleting or even, updating:
DELETE w
FROM WorkRecord2 w,
Employee e
WHERE w.EmployeeRun = e.EmployeeNo
AND w.Company = '1'
AND w.Date = '2013-05-06'
You don't specify the tables for Company and Date, and you might want to fix that.
Standard SQL using MERGE:
MERGE WorkRecord2 T
USING Employee S
ON T.EmployeeRun = S.EmployeeNo
AND Company = '1'
AND Date = '2013-05-06'
WHEN MATCHED THEN DELETE;
The answer from Devart is also standard SQL, though incomplete. It should look more like this:
DELETE
FROM WorkRecord2
WHERE EXISTS ( SELECT *
FROM Employee S
WHERE S.EmployeeNo = WorkRecord2.EmployeeRun
AND Company = '1'
AND Date = '2013-05-06' );
The important thing to note about the above is it is clear the delete is targeting a single table, as enforced in the second example by requiring a scalar subquery.
For me, the various proprietary syntax answers are harder to read and understand. I guess the mindset for is best described in the answer by frans eilering, i.e. the person writing the code doesn't necessarily care about the person who will read and maintain the code.
This is a simple query to delete the records from two table at a time.
DELETE table1.* ,
table2.*
FROM table1
INNER JOIN table2 ON table1.id= table2.id where table1.id ='given_id'
Here is my SQL Server version
DECLARE #ProfileId table(Id bigint)
DELETE FROM AspNetUsers
OUTPUT deleted.ProfileId INTO #ProfileId
WHERE Email = #email
DELETE FROM UserProfiles
WHERE Id = (Select Id FROM #ProfileId)
Delete multiple table data using transaction block, table variable and JOIN.
BEGIN TRANSACTION;
declare #deletedIds table ( id int );
DELETE w
output deleted.EmployeeRun into #deletedIds
FROM WorkRecord2 w
INNER JOIN Employee e
ON e.EmployeeNo = w.EmployeeRun
AND w.Company = 1
AND w.date = '2013-05-06';
DELETE e
FROM Employee as e
INNER JOIN #deletedIds as d
ON d.id = e.EmployeeNo;
COMMIT TRANSACTION;
Please check from url https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=43330dda6f1b71b8ec4172a24d5b6921
Delete multiple table data with temporary table and JOIN. Drop temporary table after deletion.
BEGIN TRANSACTION;
-- create temporary table
create table #deletedRecords (employeeId int);
-- INSERT INTO #deletedRecords
SELECT e.EmployeeNo
FROM WorkRecord2 w
INNER JOIN Employee e
ON e.EmployeeNo = w.EmployeeRun
AND w.Company = 1
AND w.date = '2013-05-06';
-- delete from WorkRecord2
DELETE w
FROM WorkRecord2 w
INNER JOIN #deletedRecords d
ON w.EmployeeRun = d.employeeId;
-- delete from Employee using exists
DELETE
FROM Employee
WHERE EXISTS (SELECT 1
FROM #deletedRecords d
WHERE d.employeeId = EmployeeNo);
-- drop temporary table
DROP TABLE #deletedRecords;
COMMIT TRANSACTION;
Please check from url https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=d52c6c1ed91669d68fcc6bc91cb32d78
Alternative way to create temporary tables by using SELECT INTO
BEGIN TRANSACTION;
SELECT e.EmployeeNo employeeId
INTO #deletedRecords
FROM WorkRecord2 w
INNER JOIN Employee e
ON e.EmployeeNo = w.EmployeeRun
AND w.Company = 1
AND w.date = '2013-05-06';
-- delete from WorkRecord2
DELETE w
FROM WorkRecord2 w
INNER JOIN #deletedRecords d
ON w.EmployeeRun = d.employeeId;
-- delete from Employee using exists
DELETE
FROM Employee
WHERE EXISTS (SELECT 1
FROM #deletedRecords d
WHERE d.employeeId = EmployeeNo);
-- drop temporary table
DROP TABLE #deletedRecords;
COMMIT TRANSACTION;
Please check from url https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=0f02f05616ce5b4dcc8fc67c6cf1e640
Remove a single table data using JOIN
DELETE w
FROM WorkRecord2 w
INNER JOIN Employee e
ON e.EmployeeNo = w.EmployeeRun
AND w.Company = 1
AND w.date = '2013-05-06'
Please check from url https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=84a60d1368556a8837281df36579334a
Delete single table data using CTE
WITH cte AS (
SELECT w.EmployeeRun
FROM WorkRecord2 w
WHERE EXISTS (SELECT 1
FROM Employee
WHERE EmployeeNo = w.EmployeeRun)
AND w.Company = 1
AND w.date = '2013-05-06'
)
DELETE
FROM cte
Please check from url https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=6590007b3c8c2ffad5563bd86606c5b1
Use ON CASCADE DELETE during foreign key creation in child table. If remove parent table data then corresponding child table data is automatically deleted.