Link all query (select and delete) in one - sql

I am trying to make one statement(automated) of the following queries.
All i know proposal id from my UI. i do query manually like below
select * from tblAssessment where ProposalID like '%0081/2013/0587B%'
select * from tblAssessmentVersion where AssessmentID=587
select * from tblIdentifiedThreatenedSpecies where AssessmentVersionID=731
delete from tblIdentifiedThreatenedSpecies where PercentGain=0 and AssessmentVersionID=731
once i know the proposal id ,i query in to tblassessment to get the assessment id then use the assessment id to query in to assessmentversion table to find the assessment version ID then use the assessment version id in to Identified species table to delete the record where percentgain column is 0.
Appreciate all your help,thanks in advance

You can use DELETE FROM .. JOIN:
DELETE s
FROM tblIdentifiedThreatenedSpecies s
INNER JOIN tblAssessmentVersion v
ON v.AssessmentVersionID = s.AssessmentVersionID
INNER JOIN tblAssessment a
ON a.AssessmentID = v.AssessmentID
WHERE
a.ProposalID LIKE '%0081/2013/0587B%'
AND PercentGain = 0
To check for rows to be deleted, SELECT first:
SELECT s.*
FROM tblIdentifiedThreatenedSpecies s
INNER JOIN tblAssessmentVersion v
ON v.AssessmentVersionID = s.AssessmentVersionID
INNER JOIN tblAssessment a
ON a.AssessmentID = v.AssessmentID
WHERE
a.ProposalID LIKE '%0081/2013/0587B%'
AND PercentGain = 0

join all your SELECT in one subquery
delete from tblIdentifiedThreatenedSpecies
where PercentGain=0 and AssessmentVersionID in
(
select av.Id
from
tblAssessmentVersion av
join tblAssessment a on a.Id = av.AssessmentID
where a.ProposalID like '%0081/2013/0587B%'
)

I hope this will work.
delete from tblIdentifiedThreatenedSpecies
where PercentGain=0 and AssessmentVersionID=(
select top 1 AssessmentVersionID from tblAssessmentVersion where AssessmentID=(
select top 1 AssessmentID from tblAssessment where ProposalID like '%0081/2013/0587B%'
)
);
Here top 1 is used if query returns more than one records, which is optional it your query doesn't.
Thank you.

Related

New SQL user - I'm trying to extract the latest record in my query. Accountant new to SQL

For every AbsenceBalance.AbsenceTypesUID I want to return the latest record AbsenceBalance.BalanceTime for each AbsenceBalance.EmployeeUID
I have tried select max but it only returns the most recent entry for the entire table and not by AbsenceBalance.AbsenceTypesUID or AbsenceBalance.EmployeeUID
This is my query
SELECT TOP (1000)
AbsenceBalance.[UID],
AbsenceBalance.BalanceTime,
AbsenceBalance.AbsenceTypesUID,
AbsenceBalance.Mins,
Employee.FullName,
Employee.FirstName,
Employee.LastName,
AbsenceBalance.EmployeeUID,
absencetypes.LongName
from [RiteqDB].[dbo].[AbsenceBalance]
LEFT JOIN [RiteqDB].[dbo].Employee on AbsenceBalance.EmployeeUID = Employee.UID
LEFT JOIN [RiteqDB].[dbo].AbsenceTypes on absencebalance.AbsenceTypesUID = absencetypes.UID
where AbsenceBalance.[UID] = (select max (AbsenceBalance.[UID]) from [RiteqDB].[dbo].[AbsenceBalance] where AbsenceBalance.AbsenceTypesUID = AbsenceBalance.AbsenceTypesUID)
--where Select Max(v) from (values (AbsenceBalance.BalanceTime)
order by FullName, AbsenceTypesUID
It sounds like you might need a group by link, then either use an inner select in a where (like you have) or use this with an inner join.
SELECT
Max(AbsenceBalance.[UID]),
AbsenceBalance.AbsenceTypesUID,
AbsenceBalance.EmployeeUID,
from [RiteqDB].[dbo].[AbsenceBalance]
GROUP BY AbsenceTypesUID, EmployeeUID
;with cte as (
SELECT TOP (1000) AB.[UID]
,AB.BalanceTime
,AB.AbsenceTypesUID
,AB.Mins
,E.FullName
,E.FirstName
,E.LastName
,AB.EmployeeUID
,AT.LongName
, ROW_NUMBER() OVER(PARTITION BY AB.[UID], AB.EmployeeUID order by AB.BalanceTime DESC) AS RUN
FROM [RiteqDB].[dbo].[AbsenceBalance] AB
LEFT JOIN [RiteqDB].[dbo].Employee E ON AB.EmployeeUID = E.UID
LEFT JOIN [RiteqDB].[dbo].AbsenceTypes AT ON AB.AbsenceTypesUID = AT.UID
)
select * from cte
where RUN = 1
In your where condition your comparing with itself that might be the issue.
select max (AbsenceBalance.[UID]) from [RiteqDB].[dbo].[AbsenceBalance]
where AbsenceBalance.AbsenceTypesUID = AbsenceBalance.AbsenceTypesUID
following is wrong
AbsenceBalance.AbsenceTypesUID = AbsenceBalance.AbsenceTypesUID

SQL query to retrieve last record from a linked table [duplicate]

This question already has answers here:
SQL join: selecting the last records in a one-to-many relationship
(13 answers)
Closed 6 years ago.
I wrote a query to compare 2 columns in different tables (TRELAY VS TUSERDEF8). The query works great, except that it retrieves the top record in the TUSERDEF8 table which has a many to one relationship to the TRELAY table.
The tables are linked by TRELAY.ID = TUSERDEF8.N01. I would like to retrieve the latest record from TUSERDEF8 and compare that record with the TRELAY record. I plan to use the max value of the index column (TUSERDEF8.ID) to determine the latest record.
I am using SQL Server.
My code is below, but I'm not sure how to change the query to retrieve the last TUSERDEF8 record. Any help is appreciated.
SELECT
TRELAY.ID, TRELAY.S15,
TUSERDEF8.S04, TUSERDEF8.N01, TUSERDEF8.S06
FROM
TRELAY
INNER JOIN
TUSERDEF8 ON TRELAY.ID = TUSERDEF8.N01
WHERE
LEFT(TRELAY.S15, 1) <> LEFT(TUSERDEF8.S04, 1)
AND NOT (TRELAY.S15 LIKE '%MEDIUM%' AND
TUSERDEF8.S04 LIKE '%N/A%' AND
TUSERDEF8.S06 LIKE '%EACMS%')
Making the assumption that your IDs are int(s) then the below might work?
SELECT TOP 1 TRELAY.ID, TRELAY.S15, TUSERDEF8.S04, TUSERDEF8.N01, TUSERDEF8.S06
FROM TRELAY INNER JOIN TUSERDEF8
ON TRELAY.ID = TUSERDEF8.N01
WHERE LEFT(TRELAY.S15, 1) <> LEFT(TUSERDEF8.S04, 1)
AND NOT (
TRELAY.S15 LIKE '%MEDIUM%'
AND TUSERDEF8.S04 LIKE '%N/A%'
AND TUSERDEF8.S06 LIKE '%EACMS%'
)
ORDER BY TUSERDEF8.ID DESC
HTH
Dave
You could do this:
With cteLastRecord As
(
Select S04, N01, S06,
Row_Number() Over (Partition By N01, Order By ID Desc) SortOrder
From TUSERDEF8
)
SELECT
TRELAY.ID, TRELAY.S15,
TUSERDEF8.S04, TUSERDEF8.N01, TUSERDEF8.S06
FROM
TRELAY
INNER JOIN
(Select S04, N01, S06 From cteLastRecord Where SortOrder = 1) TUSERDEF8 ON TRELAY.ID = TUSERDEF8.N01
WHERE
LEFT(TRELAY.S15, 1) <> LEFT(TUSERDEF8.S04, 1)
AND NOT (TRELAY.S15 LIKE '%MEDIUM%' AND
TUSERDEF8.S04 LIKE '%N/A%' AND
TUSERDEF8.S06 LIKE '%EACMS%')
I believe that your expected output is still a little ambiguous.
It sounds to me like you want only the record from the output where TUSERDEF8.ID is at its max. If that's correct, then try this:
SELECT TRELAY.ID, TRELAY.S15, TUSERDEF8.S04, TUSERDEF8.N01, TUSERDEF8.S06
FROM TRELAY
INNER JOIN TUSERDEF8 ON TRELAY.ID = TUSERDEF8.N01
WHERE LEFT(TRELAY.S15, 1) <> LEFT(TUSERDEF8.S04, 1)
AND NOT (TRELAY.S15 LIKE '%MEDIUM%' AND
TUSERDEF8.S04 LIKE '%N/A%' AND
TUSERDEF8.S06 LIKE '%EACMS%')
AND TUSERDEF8.ID IN (SELECT MAX(TUSERDEF8.ID) FROM TUSERDEF8)
EDIT: After reviewing your recent comments, it would seem something like this would be more suitable:
SELECT
, C.ID
, C.S15,
, D.S04
, D.N01
, D.S06
FROM (
SELECT A.ID, A.S15, MAX(B.ID) AS MaxID
FROM TRELAY AS A
INNER JOIN TUSERDEF8 AS B ON A.ID = B.N01
WHERE
LEFT(A.S15, 1) <> LEFT(B.S04, 1)
AND NOT (A.S15 LIKE '%MEDIUM%' AND
B.S04 LIKE '%N/A%' AND
B.S06 LIKE '%EACMS%')
GROUP BY A.ID, A.S15
) AS C
INNER JOIN TUSERDEF8 AS D ON C.ID = D.N01 AND C.MaxID = D.ID
Using an ID column to determine which row is "last" is a bad idea
Using cryptic table names like "TUSERDEF8" (how is it different from TUSERDEF7) is a very bad idea, along with completely cryptic column names like "S04".
Using prefixes like "T" for table is a bad idea - it should already be clear that it's a table.
Now that all of that is out of the way:
SELECT
R.ID,
R.S15,
U.S04,
U.N01,
U.S06
FROM
TRELAY R
INNER JOIN TUSERDEF8 U ON U.N01 = R.ID
LEFT OUTER JOIN TUSERDEF8 U2 ON
U2.N01 = R.ID AND
U2.ID > U.ID
WHERE
U2.ID IS NULL AND -- This will only happen if the LEFT OUTER JOIN above found no match, meaning that the row in U has the highest ID value of all matches
LEFT(R.S15, 1) <> LEFT(U.S04, 1) AND
NOT (
R.S15 LIKE '%MEDIUM%' AND
U.S04 LIKE '%N/A%' AND
U.S06 LIKE '%EACMS%'
)

Sql Query combine using Top and Ascending order

I have been creating sql query as shown below :
select * from (select DISTINCT * from (select po.tGroup_id,pp.tGroup_id as GroupID from tPhos_Line_Operator PO
LEFT join tPhos_Line_Parameter PP
on PO.tGroup_id = PP.tGroup_id) A) Ac
left JOIN
(SELECT top 1 tGroup_id FROM tGROUP_LOG order by id desc) B
on Ac.tGroup_id = B.tGroup_id
I was expecting to see records like in the image below :
But I keep getting this records :
I tried to hardcode in the left join by putting the tGroup_id=29 and it work as I got the exact record I want. Refer to first image.
select * from (select DISTINCT * from (select po.tGroup_id,pp.tGroup_id as GroupID from tPhos_Line_Operator PO
LEFT join tPhos_Line_Parameter PP
on PO.tGroup_id = PP.tGroup_id) A) Ac
left JOIN
(SELECT top 1 tGroup_id FROM tGROUP_LOG where tGroup_id = 29 order by id desc
) B
on Ac.tGroup_id = B.tGroup_id
I do not want to hardcode it.
Can someone tell me where did I missed out or did wrong?
Thanks in advance.
I have found a way, instead of using top 1, I can use max.
SELECT max(id) as TESTID,tGroup_id FROM tGROUP_LOG
group by tGroup_id
I consider this has fixed my issue. Thanks

How can I join on multiple columns within the same table that contain the same type of info?

I am currently joining two tables based on Claim_Number and Customer_Number.
SELECT
A.*,
B.*,
FROM Company.dbo.Company_Master AS A
LEFT JOIN Company.dbp.Compound_Info AS B ON A.Claim_Number = B.Claim_Number AND A.Customer_Number = B.Customer_Number
WHERE A.Filled_YearMonth = '201312' AND A.Compound_Ind = 'Y'
This returns exactly the data I'm looking for. The problem is that I now need to join to another table to get information based on a Product_ID. This would be easy if there was only one Product_ID in the Compound_Info table for each record. However, there are 10. So basically I need to SELECT 10 additional columns for Product_Name based on each of those Product_ID's that are being selected already. How can do that? This is what I was thinking in my head, but is not working right.
SELECT
A.*,
B.*,
PD_Info_1.Product_Name,
PD_Info_2.Product_Name,
....etc {Up to 10 Product Names}
FROM Company.dbo.Company_Master AS A
LEFT JOIN Company.dbo.Compound_Info AS B ON A.Claim_Number = B.Claim_Number AND A.Customer_Number = B.Customer_Number
LEFT JOIN Company.dbo.Product_Info AS PD_Info_1 ON B.Product_ID_1 = PD_Info_1.Product_ID
LEFT JOIN Company.dbo.Product_Info AS PD_Info_2 ON B.Product_ID_2 = PD_Info_2.Product_ID
.... {Up to 10 LEFT JOIN's}
WHERE A.Filled_YearMonth = '201312' AND A.Compound_Ind = 'Y'
This query not only doesn't return the correct results, it also takes forever to run. My actual SQL is a lot longer and I've changed table names, etc but I hope that you can get the idea. If it matters, I will be creating a view based on this query.
Please advise on how to select multiple columns from the same table correctly and efficiently. Thanks!
I found put my extra stuff into CTE and add ROW_NUMBER to insure that I get only 1 row that I care about. it would look something like this. I only did for first 2 product info.
WITH PD_Info
AS ( SELECT Product_ID
,Product_Name
,Effective_Date
,ROW_NUMBER() OVER ( PARTITION BY Product_ID, Product_Name ORDER BY Effective_Date DESC ) AS RowNum
FROM Company.dbo.Product_Info)
SELECT A.*
,B.*
,PD_Info_1.Product_Name
,PD_Info_2.Product_Name
FROM Company.dbo.Company_Master AS A
LEFT JOIN Company.dbo.Compound_Info AS B
ON A.Claim_Number = B.Claim_Number
AND A.Customer_Number = B.Customer_Number
LEFT JOIN PD_Info AS PD_Info_1
ON B.Product_ID_1 = PD_Info_1.Product_ID
AND B.Fill_Date >= PD_Info_1.Effective_Date
AND PD_Info_2.RowNum = 1
LEFT JOIN PD_Info AS PD_Info_2
ON B.Product_ID_2 = PD_Info_2.Product_ID
AND B.Fill_Date >= PD_Info_2.Effective_Date
AND PD_Info_2.RowNum = 1

SQL JOIN Statement

Lets say I have a table e.g
Request No. Type Status
---------------------------
1 New Renewed
and then another table
Action ID Request No LastUpdated
------------------------------------
1 1 06-10-2010
2 1 07-14-2010
3 1 09-30-2010
How can I join the second table with the first table but only get the latest record from the second table(e.g Last Updated DESC)
SELECT T1.RequestNo ,
T1.Type ,
T1.Status,
T2.ActionId ,
T2.LastUpdated
FROM TABLE1 T1
JOIN TABLE2 T2
ON T1.RequestNo = T2.RequestNo
WHERE NOT EXISTS
(SELECT *
FROM TABLE2 T2B
WHERE T2B.RequestNo = T2.RequestNo
AND T2B.LastUpdated > T2.LastUpdated
)
Using aggregates:
SELECT r.*, re.*
FROM REQUESTS r
JOIN REQUEST_EVENTS re ON re.request_no = r.request_no
JOIN (SELECT t.request_no,
MAX(t.lastupdated) AS latest
FROM REQUEST_EVENTS t
GROUP BY t.request_no) x ON x.request_no = re.request_no
AND x.latest = re.lastupdated
Using LEFT JOIN & NOT EXISTS:
SELECT r.*, re.*
FROM REQUESTS r
JOIN REQUEST_EVENTS re ON re.request_no = r.request_no
WHERE NOT EXISTS(SELECT NULL
FROM REQUEST_EVENTS re2
WHERE re2.request_no = r2.request_no
AND re2.LastUpdated > re.LastUpdated)
SELECT *
FROM REQUEST, ACTION
WHERE REQUEST.REQUESTNO = ACTION.REQUESTNO --Joining here
AND ACTION.LastUpdated = (SELECT MAX(LastUpdated) FROM ACTION WHERE REQUEST.REQUESTNO = ACTION.REQUESTNO);
A sub-query is used to get the last updated record's date and matches against itself to prevent the other records being joined.
Granted, depending on how precise the LastUpdated field is, it can have problems with two records being updated on the same date, but that is a problem encountered in any other implementation, so the precision would have to be increased or some other logic would have to be in place or another distinguishing characteristic to prevent multiple rows being returned.
SELECT r.RequestNo, r.Type, r.Status, a.ActionID, MAX(a.LastUpdated)
FROM Request r
INNER JOIN Action a ON r.RequestNo = a.RequestNo
GROUP BY r.RequestNo, r.Type, r.Status, a.ActionID
We can use the operation Top 1 with ORDER BY clause. For instance, if your tables are RequestTable(ID,Type,Status) and ActionTable(ActionID,RequestID,LastUpdated), the query will be like this:
Select Top 1 rq.ID, rq.Status, at.ActionID
From RequestTable as rq
JOIN ActionTable as at ON rq.ID = at.RequestID
Order by at.LastUpdated DESC