Remove duplicate address_id from sql data set - sql

I need to get only distinct address_id in result no duplication. Here is my query.
SELECT DISTINCT address.address_id, address.address1, address.streetcity, state.stateabbrev, rtrim(ltrim(case when address.streetzipcode is not null and address.streetzipcode != 'NULL' then address.streetzipcode else '' end))+case when len(address.streetzipplus4)>0 then '-'+rtrim(ltrim(address.streetzipplus4)) else '' end as streetzipcode, address.homephone,
dbo.f_addressstudent (student.address_id) as Students,
dbo.f_addresspeople (student.address_id) as Adults,
case
when #classif_id IS NULL then 0
else
student.classif_id
end classif,
classifctn
FROM district WITH(NOLOCK)
JOIN dbo.building ON building.district_id = district.district_id
JOIN dbo.studbldg_bridge WITH(NOLOCK) ON studbldg_bridge.bldg_id=building.bldg_id
JOIN dbo.student WITH(NOLOCK) ON student.student_id = studbldg_bridge.student_id
JOIN classif with(nolock) on student.classif_id = classif.classif_id
LEFT JOIN dbo.address WITH(NOLOCK) ON student.address_id = address.address_id
LEFT JOIN dbo.state WITH(NOLOCK) ON address.streetstate_id = state.state_id
LEFT JOIN dbo.state AS mailstate WITH(NOLOCK) ON address.state_id = mailstate.state_id
WHERE district.district_id = (SELECT district_id FROM dbo.building WITH(NOLOCK) WHERE bldg_id = #bldg_id)
ORDER BY classif,Adults, Students
Here is result of query
Query result with error in data
I have tried to group by and use aggregate function with address_id but I also have non-aggregate columns so it didn't worked for me.
After that I also tried using OVER(partition by address.address_id) but it also didn't worked.
Any help will be appreciated in advance.
Thank you
**UPDATE on Business logic/Requirements **
I need to get unique addresses for parents of students. As parent can have two or more children living in same address, it causes duplication. I need to get only one child per parent in other words.

From your image of the results it looks like the classifctn column has more than 1 value so it is repeating your row by that. In order to get 1 distinct address_id and rest of the columns either remove it from your query or you can set a precedence that will only return 1 record per address_id
further please tag only the RDBMs you ware actually using. MySQL for example doesn't have window functions yet you tagged it yet referenced using OVER(partition.... which would not be possible in mysql
;WITH cte (
SELECT DISTINCT address.address_id, address.address1, address.streetcity, state.stateabbrev, rtrim(ltrim(case when address.streetzipcode is not null and address.streetzipcode != 'NULL' then address.streetzipcode else '' end))+case when len(address.streetzipplus4)>0 then '-'+rtrim(ltrim(address.streetzipplus4)) else '' end as streetzipcode, address.homephone,
dbo.f_addressstudent (student.address_id) as Students,
dbo.f_addresspeople (student.address_id) as Adults,
case
when #classif_id IS NULL then 0
else
student.classif_id
end classif,
classifctn,
ROW_NUMBER() OVER (PARTITION BY address.address_id ORDER BY HOW WILL YOU CHOOSE?) AS RowNum
FROM district WITH(NOLOCK)
JOIN dbo.building ON building.district_id = district.district_id
JOIN dbo.studbldg_bridge WITH(NOLOCK) ON studbldg_bridge.bldg_id=building.bldg_id
JOIN dbo.student WITH(NOLOCK) ON student.student_id = studbldg_bridge.student_id
JOIN classif with(nolock) on student.classif_id = classif.classif_id
LEFT JOIN dbo.address WITH(NOLOCK) ON student.address_id = address.address_id
LEFT JOIN dbo.state WITH(NOLOCK) ON address.streetstate_id = state.state_id
LEFT JOIN dbo.state AS mailstate WITH(NOLOCK) ON address.state_id = mailstate.state_id
WHERE district.district_id = (SELECT district_id FROM dbo.building WITH(NOLOCK) WHERE bldg_id = #bldg_id)
)
SELECT *
FROM
cte
WHERE
RowNum = 1
ORDER BY
classif
,Adults
,Students
Alternatively you could nest your select query. note though this solution is somewhat useless as it will only return 1 grade/classifctn when more than 1 exists in a household if you really don't care about the column then you should just remove it from your query.
Actually both your classifctn and classif columns will cause you multiple rows when more than 1 student is at the same address. here is a way to concatenate those values to a single row. You should spend some more time on your business case and defining it for us. But here is one example for you:
SELECT DISTINCT
address.address_id
,address.address1
,address.streetcity
,state.stateabbrev
,LTRIM(RTRIM(ISNULL(NULLIF(address.streetzipcode,'NULL'),'')))
+ CASE WHEN LEN(address.streetzipplus4) > 0 THEN '-' ELSE '' END
+ LTRIM(RTRIM(ISNULL(address.streetzipplus4,''))) AS streetzipcode
,address.homephone
,dbo.f_addressstudent (student.address_id) as Students
,dbo.f_addresspeople (student.address_id) as Adults
, case
when #classif_id IS NULL then 0
else student.classif_id
end classif
,STUFF(
(SELECT ',' + CAST(classif_id AS VARCHAR(100))
FROM
classif c
WHERE c.classif = student.classif
FOR XML PATH(''))
,1,1,'') AS classifs
,STUFF(
(SELECT ',' + CAST(classifctn AS VARCHAR(100))
FROM
classif c
WHERE c.classif = student.classif
FOR XML PATH(''))
,1,1,'') AS classifctns
FROM
district WITH(NOLOCK)
INNER JOIN dbo.building
ON building.district_id = district.district_id
AND building.bldg_id = #bldg_id
INNER JOIN dbo.student WITH(NOLOCK)
ON student.student_id = studbldg_bridge.student_id
INNER JOIN dbo.address WITH(NOLOCK)
ON student.address_id = address.address_id
LEFT JOIN dbo.state WITH(NOLOCK)
ON address.streetstate_id = state.state_id
Note I when ahead and changed the zip code logic to show you some use of ISNULL() and NULLIF() that are helpful in cases like that. I also removed 3 tables because 2 are not used and the third ends up being used in a subselect to concatenate the values. Also address table was changed to an INNER JOIN because if an address doesn't exist all of the other information becomes blank/useless....
INNER JOIN dbo.studbldg_bridge WITH(NOLOCK) ON studbldg_bridge.bldg_id=building.bldg_id
LEFT JOIN dbo.state AS mailstate WITH(NOLOCK) ON address.state_id = mailstate.state_id
INNER JOIN classif with(nolock) on student.classif_id = classif.classif_id

Related

Where Clause Using Conditional Statement

i have query below
SELECT #RoleUser = MR.Code FROM MasterRole MR INNER JOIN MasterUsersRole MUR ON MR.Id = MUR.RoleId
INNER JOIN MasterUsers MU ON Mu.UserCode = MUR.UserCode
WHERE MU.UserCode = #UserLoginID
select 1 Num
, MyHistory.ID
, MyHistory.RequestNumber
, MyHistory.FlowID
, MyHistory.FlowProcessStatusID
from
(
select *
from Requests R
inner join
(
--DECLARE #UserLoginID nvarchar(200) = 'dum.testing.3'
select distinct
RequestID
from dbo.RequestTrackingHistory RTH
where IIF(#UserLoginID = 'admin', #UserLoginID, RTH.CreatedBy) = #UserLoginID
OR ( CreatedBy IN
SELECT Mu.UserCode from MasterUsers MU
INNER JOIN MasterUsersRole MUR ON MU.UserCode = MUR.UserCode
INNER JOIN MasterRole MR ON MUR.RoleId = MR.Id
WHERE MR.Code = #RoleUser
)
)
) RT on R.ID = RT.RequestID
) as MyHistory
inner join MasterFlow F on MyHistory.FlowID = F.ID
inner join
(
select FP.ID
, FP.Name
, FP.AssignType
, FP.AssignTo
, FP.IsStart
, case FP.AssignType
when 'GROUP' then
G.Name
end as 'AssignToName'
from MasterFlowProcess FP
left join dbo.MasterRole G on FP.AssignTo = G.ID and FP.AssignType = 'GROUP'
) FP on MyHistory.FlowProcessID = FP.ID
inner join MasterFlowProcessStatus FPS on MyHistory.FlowProcessStatusID = FPS.ID
left join MasterFlowProcessStatusNext FPSN on FPS.ID = FPSN.ProcessStatusFlowID
left join MasterFlowProcess FPN on FPSN.NextProcessFlowID = FPN.ID
left JOIN MasterRole MR ON MR.Id = FPN.AssignTo
left join MasterUsersRole MUR on MR.Id = MUR.RoleId
left join MasterUsers MURO on MUR.UserCode = MURO.UserCode
inner join MasterUsers UC on MyHistory.CreatedBy = UC.UserCode
left join MasterUsers UU on MyHistory.UpdatedBy = UU.UserCode
LEFT JOIN RequestMT RMT ON MyHistory.ID = RMT.RequestID
LEFT JOIN RequestGT RGT ON MyHistory.ID = RGT.RequestID
left join (SELECT sum(QtyCU) countQty , RequestId from dbo.RequestGTDetail where IsActive = 1 group by RequestId) RGTD on RGTD.RequestId = RGT.RequestId
left join (SELECT sum(QtyPCS) countQty , RequestId from dbo.RequestMTDetail where IsActive = 1 group by RequestId) RMTD on RMTD.RequestId = RMT.RequestId
left join (SELECT COUNT(IIF(returnable = 0, returnable, null)) countReturnable , RequestId from dbo.RequestMTDetail group by RequestId) RMTR on RMTR.RequestId = RMT.RequestId
left JOIN dbo.MasterDistributor md ON md.Code = RGT.CustId or md.Code = RMT.CustId
left JOIN dbo.MasterUsersDistributor MUD ON MUD.UserCode = MURO.UserCode AND md.Code = MUD.DistributorCode
LEFT JOIN dbo.MasterReason MRMT ON RMT.ReasonId = MRMT.Id
LEFT JOIN dbo.MasterReason MRGT ON RGT.ReasonId = MRGT.Id
LEFT JOIN dbo.MasterDistributorGroup MDG ON MDG.Id = MD.GroupId
OUTER APPLY dbo.FnGetHistoryApproveDate(MyHistory.Id) AS x
where REPLACE(FPS.Name, '#Requestor', uc.Name) <> 'DRAFT'
AND MUD.DistributorCode IN (SELECT DistributorCode FROM dbo.MasterUsersDistributor WHERE UserCode = #UserLoginID)
i want to add some logic in where clause
this line
==> AND MUD.DistributorCode IN (SELECT DistributorCode FROM dbo.MasterUsersDistributor WHERE UserCode = #UserLoginID)
it depend on the #RoleUser variable, if #RoleUser IN ('A','B') then where clause above is executed, but if #RoleUser Not IN ('A','B') where clause not executed
i,m trying this where clause
AND IIF(#RoleUser IN ('A','B'), MUD.DistributorCode, #RoleUser) IN (SELECT DistributorCode FROM dbo.MasterUsersDistributor WHERE UserCode = IIF(#RoleUser IN ('A','B'), #UserLoginID, NULL))
it didn't work, only executed if #RoleUser IS ('A','B') other than that it return 0 record
any help or advice is really appreciated
thank you
The cleanest way I'm implemented these kind of crazy rules is a
holderTable
and a countVariable against the holder table.
I'll give a generic examples.
This is a "approach" and "philosophy", not a specific answer....with complex WHERE clauses.
DECLARE #customerCountryCount int
DECLARE #customerCountry TABLE ( CountryName varchar(15) )
if ( "the moon is blue on tuesday" ) /* << whatever rules you have */
BEGIN
INSERT INTO #customerCountry SELECT "Honduras" UNION ALL SELECT "Malaysia"
END
if ( "favorite color = green" ) /* << whatever rules you have */
BEGIN
INSERT INTO #customerCountry SELECT "Greenland" UNION ALL SELECT "Peru"
END
SELECT #customerCountryCount = COUNT(*) FROM #customerCountry
Select * from dbo.Customers c
WHERE
(#customerCountryCount = 0)
OR
( exists (select null from #customerCountry innerVariableTable where UPPER(innerVariableTable.CountryName) = UPPER(c.Country) ))
)
This way, instead of putting all the "twisted logic" in an overly complex WHERE statement..... you have "separation of concerns"...
Your inserts into #customerCountry are separated from your use of #customerCountry.
And you have the #customerCountryCount "trick" to distinguish when nothing was used.
You can add a #customerCountryNotExists table as well, and code it to where not exists.
As a side note, you may want to try using a #temp table (instead of a #variabletable (#customerCountry above)... and performance test these 2 options.
There is no "single answer". You have to "try it out".
And many many variables go into #temp table performance (from a sql-server SETUP, not "how you code a stored procedure". That is way outside the scope of this question.
Here is a SOF link to "safe" #temp table usage.
Temporary table in SQL server causing ' There is already an object named' error

SQL SELECT clause with WHERE statement for specific order

I have a through table, doctor_specialties that has a column ordinal that I would like to use in order to create a column named primary_specialty and also secondary_specialty. The logic for primary_specialty is WHERE ordinal == 1.
How can I add the primary_specialty and secondary_specialty columns? One approach would be to use a WHERE statement with the INNER JOIN but I think that would be less efficient?
SELECT pd.name AS "doctor_name",
s.name AS "primary_specialty" WHERE ds.ordinal == 1
FROM doctor_profiles AS dp
INNER JOIN doctor_specialties AS ds on dp.id = ds.doctor_profile_id
INNER JOIN specialties AS s on ds.specialty_id = s.id
Desired output is
name primary_specialty secondary_specialty
Josh Dermatology, Cosmetic Dermatology
Linda Primary Care null
You need to achive this by using case statement. example is shared below
SELECT pd.name AS "doctor_name",
case when ds.ordinal = 1 then s.name end as "primary_specialty",
case when ds.ordinal <> 1 then s.name end as "secondary_specialty"
FROM doctor_profiles AS dp
INNER JOIN doctor_specialties AS ds on dp.id = ds.doctor_profile_id
INNER JOIN specialties AS s on ds.specialty_id = s.id
You can use conditional aggregation:
SELECT dp.name AS "doctor_name",
MAX(CASE WHEN ds.ordinal = 1 THEN s.name END) AS "primary_specialty",
MAX(CASE WHEN ds.ordinal != 2 THEN s.name END) AS "secondary_specialty"
FROM doctor_profiles AS dp
INNER JOIN doctor_specialties AS ds on dp.id = ds.doctor_profile_id
INNER JOIN specialties AS s on ds.specialty_id = s.id
GROUP BY pd.name
You can alter the existing, or use additional MAX aggregates containing CASE expressions, in order to implement the logic for secondary specialties.

SQL Server Query Returning Same Row Twice

I seem to be having trouble with the following query. It basically works, but I have a case where it is returning one row from mc_WorkoutDetails twice!
Here's the original query:
ALTER PROCEDURE [dbo].[mc_Workouts_GetActivities]
#WorkoutID bigint
AS
BEGIN
SET NOCOUNT ON
SELECT d.ID, a.Description,
CASE WHEN Reps = 0 THEN NULL ELSE Reps END AS Reps,
CASE WHEN Sets = 0 THEN NULL ELSE Sets END AS Sets,
CASE WHEN Minutes = 0 THEN NULL ELSE Minutes END AS Minutes,
d.Comments, c.Name AS Category, a.CategoryID,
(CASE WHEN v.ActivityID IS NULL THEN 0 ELSE 1 END) AS HasVideo,
a.ID AS ActivityID
FROM mc_WorkoutDetails d
INNER JOIN mc_Activities a ON d.ActivityID = a.ID
INNER JOIN mc_Activities_Categories c ON a.CategoryID = c.ID
LEFT OUTER JOIN mc_TrainerVideos v ON a.ID = v.ActivityID
WHERE (d.WorkoutID = #WorkoutID)
ORDER BY SortOrder, a.Description
RETURN ##ERROR
END
Then I tried changing:
INNER JOIN mc_Activities a ON d.ActivityID = a.ID
INNER JOIN mc_Activities_Categories c ON a.CategoryID = c.ID
To:
LEFT OUTER JOIN mc_Activities a ON d.ActivityID = a.ID
LEFT OUTER JOIN mc_Activities_Categories c ON a.CategoryID = c.ID
But that didn't seem to help. I still get the duplicate row.
Can anyone see what's happening?
What you can do is add a join back to the same table using a group to weed out the duplicate rows.
So add this to your join after FROM mc_WorkoutDetails d:
inner join (select [columns you want to select], max(id) id
from mc_WorkoutDetails
group by [columns you want to select] ) q on q.id = d.id
Let me know if that makes sense. Basically you are doing a distinct and getting the max id so you eliminate one of the rows in the join. You have to remember that even if you want there to be duplicates, they will be eliminated even if they are suppose to be there.
The full alter would be:
ALTER PROCEDURE [dbo].[mc_Workouts_GetActivities]
#WorkoutID bigint
AS
BEGIN
SET NOCOUNT ON
SELECT d.ID, a.Description,
CASE WHEN Reps = 0 THEN NULL ELSE Reps END AS Reps,
CASE WHEN Sets = 0 THEN NULL ELSE Sets END AS Sets,
CASE WHEN Minutes = 0 THEN NULL ELSE Minutes END AS Minutes,
d.Comments, c.Name AS Category, a.CategoryID,
(CASE WHEN v.ActivityID IS NULL THEN 0 ELSE 1 END) AS HasVideo,
a.ID AS ActivityID
FROM mc_WorkoutDetails d
inner join (select Reps, Sets, Comments, Minutes, max(id) id
from mc_WorkoutDetails
group by Reps, Sets, Comments, Minutes ) q on q.id = d.id
INNER JOIN mc_Activities a ON d.ActivityID = a.ID
INNER JOIN mc_Activities_Categories c ON a.CategoryID = c.ID
LEFT OUTER JOIN mc_TrainerVideos v ON a.ID = v.ActivityID
WHERE (d.WorkoutID = #WorkoutID)
ORDER BY SortOrder, a.Description
RETURN ##ERROR
END
Thanks for everyone's input. The general suggestions here were correct: I had two rows in the mc_workoutDetails table that referenced the same row in the mc_Activities table.
While the foreign key was part of a unique primary key, it was a compound key and so this column could contain duplicates as long as the other column in the key were different.

SQL-subquery workaround to join based on alias

Attempted Subquery using alias
SELECT
*,
IQ.EndPart,
IQ.QtyToShip
FROM
parts p
INNER JOIN (
select
*,
(case when c.kitno is null then l.partno else c.partno end) as [EndPart],
(case when c.kitno is null then l.TotalQuantity else c.reqqty end) as [QtyToShip]
FROM
shipments s
INNER JOIN shipments_li l ON s.ShipmentNo = l.ShipmentNo
LEFT JOIN ProductConfiguration c ON l.PartNo = c.KitNo WHERE s.Status='N' and year(s.OrderDate)>2007
) IQ ON p.partno = IQ.EndPart
Looking for a way to join the parts table to my query below, using the part # which is aliased as EndPart. If there is another way to acheive the results of taking two columns and combining them instead of case and an alias that would be a great alternative as well. All my searches of other individuals quest to achieve the same have yielded the result you cannot perform a join based on alias because the results have not been determined at that point, recommending a subquery as a workaround. I'm just not sure how to acheive working results. The above query was what I attempted to get working. Any help appreciated. Thanks in advance.
Original Query
SELECT
*,
(case when c.kitno is null then l.partno else c.partno end) as [EndPart],
(case when c.kitno is null then l.TotalQuantity else c.reqqty end) as [QtyToShip]
FROM
shipments s
INNER JOIN shipments_li l ON s.ShipmentNo = l.ShipmentNo
LEFT JOIN ProductConfiguration c ON l.PartNo = c.KitNo
WHERE
s.Status='N'
and year(s.OrderDate)>2007
order by s.shipmentno
More proper way
--- CREATE TempTable
DECLARE #tblTemp AS TABLE (EndPart INT,
QtyToShip INT)
INSERT INTO #tblTemp (EndPart, QtyToShip)
SELECT
(CASE WHEN c.kitno IS NULL
THEN l.partno ELSE c.partno END) AS [EndPart],
(CASE WHEN c.kitno IS NULL
THEN l.TotalQuantity
ELSE c.reqqty END) AS [QtyToShip]
FROM dbo.Shipments s WITH(NOLOCK)
INNER JOIN shipments_li l WITH(NOLOCK) ON s.ShipmentNo = l.ShipmentNo
LEFT JOIN ProductConfiguration c WITH(NOLOCK) ON l.PartNo = c.KitNo
WHERE s.Status='N' AND YEAR(s.OrderDate)>2007
SELECT
p.*,
tmp.EndPart,
tmp.QtyToShip
FROM dbo.parts p WITH(NOLOCK)
INNER JOIN #tblTemp tmp ON p.partno = tmp.EndPart

TSQL Conditionally Select Specific Value

This is a follow-up to #1644748 where I successfully answered my own question, but Quassnoi helped me to realize that it was the wrong question. He gave me a solution that worked for my sample data, but I couldn't plug it back into the parent stored procedure because I fail at SQL 2005 syntax. So here is an attempt to paint the broader picture and ask what I actually need.
This is part of a stored procedure that returns a list of items in a bug tracking application I've inherited. There are are over 100 fields and 26 joins so I'm pulling out only the mostly relevant bits.
SELECT
tickets.ticketid,
tickets.tickettype,
tickets_tickettype_lu.tickettypedesc,
tickets.stage,
tickets.position,
tickets.sponsor,
tickets.dev,
tickets.qa,
DATEDIFF(DAY, ticket_history_assignment.savedate, GETDATE()) as 'daysinqueue'
FROM
dbo.tickets WITH (NOLOCK)
LEFT OUTER JOIN dbo.tickets_tickettype_lu WITH (NOLOCK) ON tickets.tickettype = tickets_tickettype_lu.tickettypeid
LEFT OUTER JOIN dbo.tickets_history_assignment WITH (NOLOCK) ON tickets_history_assignment.ticketid = tickets.ticketid
AND tickets_history_assignment.historyid = (
SELECT
MAX(historyid)
FROM
dbo.tickets_history_assignment WITH (NOLOCK)
WHERE
tickets_history_assignment.ticketid = tickets.ticketid
GROUP BY
tickets_history_assignment.ticketid
)
WHERE
tickets.sponsor = #sponsor
The area of interest is the daysinqueue subquery mess. The tickets_history_assignment table looks roughly as follows
declare #tickets_history_assignment table (
historyid int,
ticketid int,
sponsor int,
dev int,
qa int,
savedate datetime
)
insert into #tickets_history_assignment values (1521402, 92774,20,14, 20, '2009-10-27 09:17:59.527')
insert into #tickets_history_assignment values (1521399, 92774,20,14, 42, '2009-08-31 12:07:52.917')
insert into #tickets_history_assignment values (1521311, 92774,100,14, 42, '2008-12-08 16:15:49.887')
insert into #tickets_history_assignment values (1521336, 92774,100,14, 42, '2009-01-16 14:27:43.577')
Whenever a ticket is saved, the current values for sponsor, dev and qa are stored in the tickets_history_assignment table with the ticketid and a timestamp. So it is possible for someone to change the value for qa, but leave sponsor alone.
What I want to know, based on all of these conditions, is the historyid of the record in the tickets_history_assignment table where the sponsor value was last changed so that I can calculate the value for daysinqueue. If a record is inserted into the history table, and only the qa value has changed, I don't want that record. So simply relying on MAX(historyid) won't work for me.
Quassnoi came up with the following which seemed to work with my sample data, but I can't plug it into the larger query, SQL Manager bitches about the WITH statement.
;WITH rows AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY ticketid ORDER BY savedate DESC) AS rn
FROM #Table
)
SELECT rl.sponsor, ro.savedate
FROM rows rl
CROSS APPLY
(
SELECT TOP 1 rc.savedate
FROM rows rc
JOIN rows rn
ON rn.ticketid = rc.ticketid
AND rn.rn = rc.rn + 1
AND rn.sponsor <> rc.sponsor
WHERE rc.ticketid = rl.ticketid
ORDER BY
rc.rn
) ro
WHERE rl.rn = 1
I played with it yesterday afternoon and got nowhere because I don't fundamentally understand what is going on here and how it should fit into the larger context.
So, any takers?
UPDATE
Ok, here's the whole thing. I've been switching some of the table and column names in an attempt to simplify things so here's the full unedited mess.
snip - old bad code
Here are the errors:
Msg 102, Level 15, State 1, Procedure usp_GetProjectRecordsByAssignment, Line 159
Incorrect syntax near ';'.
Msg 102, Level 15, State 1, Procedure usp_GetProjectRecordsByAssignment, Line 179
Incorrect syntax near ')'.
Line numbers are of course not correct but refer to
;WITH rows AS
And the ')' char after the WHERE rl.rn = 1
)
Respectively
Is there a tag for extra super long question?
UPDATE #2
Here is the finished query for anyone who may need this:
CREATE PROCEDURE [dbo].[usp_GetProjectRecordsByAssignment]
(
#assigned numeric(18,0),
#assignedtype numeric(18,0)
)
AS
SET NOCOUNT ON
WITH rows AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY recordid ORDER BY savedate DESC) AS rn
FROM projects_history_assignment
)
SELECT projects_records.recordid,
projects_records.recordtype,
projects_recordtype_lu.recordtypedesc,
projects_records.stage,
projects_stage_lu.stagedesc,
projects_records.position,
projects_position_lu.positiondesc,
CASE projects_records.clientrequested
WHEN '1' THEN 'Yes'
WHEN '0' THEN 'No'
END AS clientrequested,
projects_records.reportingmethod,
projects_reportingmethod_lu.reportingmethoddesc,
projects_records.clientaccess,
projects_clientaccess_lu.clientaccessdesc,
projects_records.clientnumber,
projects_records.project,
projects_lu.projectdesc,
projects_records.version,
projects_version_lu.versiondesc,
projects_records.projectedversion,
projects_version_lu_projected.versiondesc AS projectedversiondesc,
projects_records.sitetype,
projects_sitetype_lu.sitetypedesc,
projects_records.title,
projects_records.module,
projects_module_lu.moduledesc,
projects_records.component,
projects_component_lu.componentdesc,
projects_records.loginusername,
projects_records.loginpassword,
projects_records.assistedusername,
projects_records.browsername,
projects_browsername_lu.browsernamedesc,
projects_records.browserversion,
projects_records.osname,
projects_osname_lu.osnamedesc,
projects_records.osversion,
projects_records.errortype,
projects_errortype_lu.errortypedesc,
projects_records.gsipriority,
projects_gsipriority_lu.gsiprioritydesc,
projects_records.clientpriority,
projects_clientpriority_lu.clientprioritydesc,
projects_records.scheduledstartdate,
projects_records.scheduledcompletiondate,
projects_records.projectedhours,
projects_records.actualstartdate,
projects_records.actualcompletiondate,
projects_records.actualhours,
CASE projects_records.billclient
WHEN '1' THEN 'Yes'
WHEN '0' THEN 'No'
END AS billclient,
projects_records.billamount,
projects_records.status,
projects_status_lu.statusdesc,
CASE CAST(projects_records.assigned AS VARCHAR(5))
WHEN '0' THEN 'N/A'
WHEN '10000' THEN 'Unassigned'
WHEN '20000' THEN 'Client'
WHEN '30000' THEN 'Tech Support'
WHEN '40000' THEN 'LMI Tech Support'
WHEN '50000' THEN 'Upload'
WHEN '60000' THEN 'Spider'
WHEN '70000' THEN 'DB Admin'
ELSE rtrim(users_assigned.nickname) + ' ' + rtrim(users_assigned.lastname)
END AS assigned,
CASE CAST(projects_records.assigneddev AS VARCHAR(5))
WHEN '0' THEN 'N/A'
WHEN '10000' THEN 'Unassigned'
ELSE rtrim(users_assigneddev.nickname) + ' ' + rtrim(users_assigneddev.lastname)
END AS assigneddev,
CASE CAST(projects_records.assignedqa AS VARCHAR(5))
WHEN '0' THEN 'N/A'
WHEN '10000' THEN 'Unassigned'
ELSE rtrim(users_assignedqa.nickname) + ' ' + rtrim(users_assignedqa.lastname)
END AS assignedqa,
CASE CAST(projects_records.assignedsponsor AS VARCHAR(5))
WHEN '0' THEN 'N/A'
WHEN '10000' THEN 'Unassigned'
ELSE rtrim(users_assignedsponsor.nickname) + ' ' + rtrim(users_assignedsponsor.lastname)
END AS assignedsponsor,
projects_records.clientcreated,
CASE projects_records.clientcreated
WHEN '1' THEN 'Yes'
WHEN '0' THEN 'No'
END AS clientcreateddesc,
CASE projects_records.clientcreated
WHEN '1' THEN rtrim(clientusers_createuser.firstname) + ' ' + rtrim(clientusers_createuser.lastname) + ' (Client)'
ELSE rtrim(users_createuser.nickname) + ' ' + rtrim(users_createuser.lastname)
END AS createuser,
projects_records.createdate,
projects_records.savedate,
projects_resolution.sitesaffected,
projects_sitesaffected_lu.sitesaffecteddesc,
DATEDIFF(DAY, projects_history_assignment.savedate, GETDATE()) as 'daysinqueue',
projects_records.iOnHitList,
projects_records.changetype
FROM
dbo.projects_records WITH (NOLOCK)
LEFT OUTER JOIN dbo.projects_recordtype_lu WITH (NOLOCK) ON projects_records.recordtype = projects_recordtype_lu.recordtypeid
LEFT OUTER JOIN dbo.projects_stage_lu WITH (NOLOCK) ON projects_records.stage = projects_stage_lu.stageid
LEFT OUTER JOIN dbo.projects_position_lu WITH (NOLOCK) ON projects_records.position = projects_position_lu.positionid
LEFT OUTER JOIN dbo.projects_reportingmethod_lu WITH (NOLOCK) ON projects_records.reportingmethod = projects_reportingmethod_lu.reportingmethodid
LEFT OUTER JOIN dbo.projects_lu WITH (NOLOCK) ON projects_records.project = projects_lu.projectid
LEFT OUTER JOIN dbo.projects_version_lu WITH (NOLOCK) ON projects_records.version = projects_version_lu.versionid
LEFT OUTER JOIN dbo.projects_version_lu projects_version_lu_projected WITH (NOLOCK) ON projects_records.projectedversion = projects_version_lu_projected.versionid
LEFT OUTER JOIN dbo.projects_sitetype_lu WITH (NOLOCK) ON projects_records.sitetype = projects_sitetype_lu.sitetypeid
LEFT OUTER JOIN dbo.projects_module_lu WITH (NOLOCK) ON projects_records.module = projects_module_lu.moduleid
LEFT OUTER JOIN dbo.projects_component_lu WITH (NOLOCK) ON projects_records.component = projects_component_lu.componentid
LEFT OUTER JOIN dbo.projects_browsername_lu WITH (NOLOCK) ON projects_records.browsername = projects_browsername_lu.browsernameid
LEFT OUTER JOIN dbo.projects_osname_lu WITH (NOLOCK) ON projects_records.osname = projects_osname_lu.osnameid
LEFT OUTER JOIN dbo.projects_errortype_lu WITH (NOLOCK) ON projects_records.errortype = projects_errortype_lu.errortypeid
LEFT OUTER JOIN dbo.projects_resolution WITH (NOLOCK) ON projects_records.recordid = projects_resolution.recordid
LEFT OUTER JOIN dbo.projects_sitesaffected_lu WITH (NOLOCK) ON projects_resolution.sitesaffected = projects_sitesaffected_lu.sitesaffectedid
LEFT OUTER JOIN dbo.projects_gsipriority_lu WITH (NOLOCK) ON projects_records.gsipriority = projects_gsipriority_lu.gsipriorityid
LEFT OUTER JOIN dbo.projects_clientpriority_lu WITH (NOLOCK) ON projects_records.clientpriority = projects_clientpriority_lu.clientpriorityid
LEFT OUTER JOIN dbo.projects_status_lu WITH (NOLOCK) ON projects_records.status = projects_status_lu.statusid
LEFT OUTER JOIN dbo.projects_clientaccess_lu WITH (NOLOCK) ON projects_records.clientaccess = projects_clientaccess_lu.clientaccessid
LEFT OUTER JOIN dbo.users users_assigned WITH (NOLOCK) ON projects_records.assigned = users_assigned.userid
LEFT OUTER JOIN dbo.users users_assigneddev WITH (NOLOCK) ON projects_records.assigneddev = users_assigneddev.userid
LEFT OUTER JOIN dbo.users users_assignedqa WITH (NOLOCK) ON projects_records.assignedqa = users_assignedqa.userid
LEFT OUTER JOIN dbo.users users_assignedsponsor WITH (NOLOCK) ON projects_records.assignedsponsor = users_assignedsponsor.userid
LEFT OUTER JOIN dbo.users users_createuser WITH (NOLOCK) ON projects_records.createuser = users_createuser.userid
LEFT OUTER JOIN dbo.clientusers clientusers_createuser WITH (NOLOCK) ON projects_records.createuser = clientusers_createuser.userid
LEFT OUTER JOIN dbo.projects_history_assignment WITH (NOLOCK) ON projects_history_assignment.recordid = projects_records.recordid
AND projects_history_assignment.historyid = (
SELECT ro.historyid
FROM rows rl
CROSS APPLY
(
SELECT TOP 1 rc.historyid
FROM rows rc
JOIN rows rn
ON rn.recordid = rc.recordid
AND rn.rn = rc.rn + 1
AND rn.assigned <> rc.assigned
WHERE rc.recordid = rl.recordid
ORDER BY
rc.rn
) ro
WHERE rl.rn = 1
AND rl.recordid = projects_records.recordid
)
WHERE
(#assignedtype='0' and projects_records.assigned = #assigned)
OR (#assignedtype='1' and projects_records.assigneddev = #assigned)
OR (#assignedtype='2' and projects_records.assignedqa = #assigned)
OR (#assignedtype='3' and projects_records.assignedsponsor = #assigned)
OR (#assignedtype='4' and projects_records.createuser = #assigned)
WITH rows AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY ticketid ORDER BY savedate DESC) AS rn
FROM #Table
)
SELECT projects_records.recordid,
projects_records.recordtype,
/* skipped */
AND projects_history_assignment.historyid = (
SELECT ro.historyid
FROM rows rl
CROSS APPLY
(
SELECT TOP 1 rc.savedate
FROM rows rc
JOIN rows rn
ON rn.recordid = rc.recordid
AND rn.rn = rc.rn + 1
AND rn.assigned <> rc.assigned
WHERE rc.recordid = rl.recordid
ORDER BY
rc.rn
) ro
WHERE rl.rn = 1
AND rl.recordid = projects_records.recordid
)
Well, if that query does not work out -- you could always consider a trigger on the tickets_history_assignment table. You could use INSTEAD OF INSERT, UPDATE which fires before any changes are made, so you would have full control of what is about to change and what to do.