I am trying to get the most recent note(comment) of a log in sql
Here is my query and what it returns:
SELECT Project.SupportLogNote.SupportLogID_SupportLogID, Project.SupportLogNote.Note, CAST(Project.SupportLogNote.NoteDate AS Date) AS NoteDate, Project.SupportLogNote.ContactID_CreatorID,
sop.bb_contacts.firstName + ' ' + sop.bb_contacts.lastName AS fullName, Project.SupportLogNote.clientId, Project.SupportLog.StatusID_StatusID
FROM Project.SupportLogNote INNER JOIN
sop.bb_contacts ON Project.SupportLogNote.ContactID_CreatorID = sop.bb_contacts.id INNER JOIN
Project.SupportLog ON Project.SupportLogNote.SupportLogID_SupportLogID = Project.SupportLog.SupportLogID
WHERE (Project.SupportLogNote.ContactID_CreatorID = 109)
ORDER BY Project.SupportLogNote.SupportLogID_SupportLogID DESC
I want to get the most recent Note from the Log so there is only 1 SupportLogID and the most recent note corresponding to that ID.
Thanks for your help guys.
Something along these lines should get you close. Please notice how I used aliases here. It removed tons of code and makes this wall of text into something far more manageable. Also, three part naming in the list of columns has been deprecated. They are going to force you to use aliases at some point.
select *
from
(
SELECT sln.SupportLogID_SupportLogID
, sln.Note
, CAST(sln.NoteDate AS Date) AS NoteDate
, sln.ContactID_CreatorID
, c.firstName + ' ' + c.lastName AS fullName
, sln.clientId
, sl.StatusID_StatusID
, ROW_NUMBER() over (partition by sl.SupportLogID order by sln.NoteDate desc) as RowNum
FROM Project.SupportLogNote sln
INNER JOIN sop.bb_contacts c ON sln.ContactID_CreatorID = c.id
INNER JOIN Project.SupportLog sl ON sln.SupportLogID_SupportLogID = sl.SupportLogID
WHERE sln.ContactID_CreatorID = 109
) x
where x.RowNum = 1
ORDER BY x.SupportLogID_SupportLogID DESC
Another option is using the WITH TIES in concert with Row_Number()
SELECT Top 1 with ties
Project.SupportLogNote.SupportLogID_SupportLogID
, Project.SupportLogNote.Note
, CAST(Project.SupportLogNote.NoteDate AS Date) AS NoteDate
, Project.SupportLogNote.ContactID_CreatorID
, sop.bb_contacts.firstName + ' ' + sop.bb_contacts.lastName AS fullName
, Project.SupportLogNote.clientId
, Project.SupportLog.StatusID_StatusID
FROM Project.SupportLogNote
INNER JOIN sop.bb_contacts ON Project.SupportLogNote.ContactID_CreatorID = sop.bb_contacts.id
INNER JOIN Project.SupportLog ON Project.SupportLogNote.SupportLogID_SupportLogID = Project.SupportLog.SupportLogID
WHERE (Project.SupportLogNote.ContactID_CreatorID = 109)
ORDER BY Row_Number() over (Partition By SupportLogID Order By NoteDate Desc)
I think cross apply might be a simple way to do this:
SELECT sln.SupportLogID_SupportLogID, sln.Note, CAST(sln.NoteDate AS Date) AS NoteDate,
sln.ContactID_CreatorID,
c.firstName + ' ' + sop.bb_contacts.lastName AS fullName, sln.clientId, sl.StatusID_StatusID
FROM Project.SupportLogNote sln INNER JOIN
sop.bb_contacts c
ON sln.ContactID_CreatorID = c.id CROSS APPLY
(SELECT TOP 1 sl.*
FROM p.SupportLog sl
WHERE sln.SupportLogID_SupportLogID =sl.SupportLogID
ORDER BY sl.NoteDate DESC
) sl
WHERE sln.ContactID_CreatorID = 109
ORDER BY sln.SupportLogID_SupportLogID DESC;
Related
i have a table which shows me workhours of postoffices, the problem is that sometimes there are duplicates: for example i have saturday showing twice from one postoffice with the same time.
Solution is to show only 1 saturday with MAX(ID), but i can't deal with that and tha think is that i don't have to show id in select.
this is my script
SELECT h.ID,
h.POSTINDEX,
H.LONGNAME_UA,
h.SHORTNAME_UA,
pt.LONGNAME_UA,
h.parent_Id,
WORKCOMMENT,
INTERVALTYPE,
TO_CHAR(TFROM, 'HH24:MI') AS TFROM,
TO_CHAR(TTO, 'HH24:MI'),
WD.NAME_UA,
WD.NAME_EN,
WD.NAME_RU,
WD.SHORTNAME_UA,
pt.isVPZ,
lr.NAME_UA,
lr.CODE
FROM ADDR_PO_WORKSCHEDULE tt
LEFT JOIN ADDR_POSTOFFICE h
ON tt.POSTOFFICE_ID = h.ID
INNER JOIN mdm_lockReason lr
ON lr.id = H.LOCK_REASON
INNER JOIN ADDR_POSTOFFICEtype pt
ON pt.ID = H.POSTOFFICETYPE_ID
INNER JOIN ADDR_PO_WORKDAYS wd
ON wd.ID = tt.dayofweek
where tt.datestop = TO_DATE('9999-12-31','YYYY-MM-DD') AND tt.postoffice_id = 8221
HAVING MAX(tt.ID)
ORDER BY h.postIndex,
h.POSTOFFICETYPE_ID,
dayofweek,
intervaltype,
tFrom,
tto
as you can see there i've add HAVING MAX(tt.ID) but i understand that it is incorrect and don't know how to solve that. help please!
You can use row_number():
with t as (
<your query here with no `having` and with tt.id as tt_id>
)
select t.*
from (select t.*, row_number() over (order by tt_id desc) as seqnum
from t
) t
where seqnum = 1;
If the source of your duplicate rows is coming from the ADDR_PO_WORKSCHEDULE table, then you can just de-dupe it before you use it in the rest of your query:
SELECT
h.ID, h.POSTINDEX, h.LONGNAME_UA, h.SHORTNAME_UA, pt.LONGNAME_UA, h.parent_Id,
WORKCOMMENT, INTERVALTYPE, TO_CHAR(TFROM, 'HH24:MI') AS TFROM, TO_CHAR(TTO, 'HH24:MI'),
WD.NAME_UA, WD.NAME_EN, WD.NAME_RU, WD.SHORTNAME_UA, pt.isVPZ, lr.NAME_UA, lr.CODE
FROM (
SELECT src.*
FROM (
SELECT t.*,
ROW_NUMBER() OVER(
PARTITION BY tt.postoffice_id, tt.dayofweek -- Group by post office / day of week
ORDER BY <order_columns> -- Rank rows within each group
) AS RowNum
FROM ADDR_PO_WORKSCHEDULE t
) src
WHERE RowNum = 1
) tt
LEFT JOIN ADDR_POSTOFFICE h ON tt.POSTOFFICE_ID = h.ID
INNER JOIN mdm_lockReason lr ON lr.id = H.LOCK_REASON
INNER JOIN ADDR_POSTOFFICEtype pt ON pt.ID = H.POSTOFFICETYPE_ID
INNER JOIN ADDR_PO_WORKDAYS wd ON wd.ID = tt.dayofweek
WHERE tt.datestop = TO_DATE('9999-12-31','YYYY-MM-DD')
AND tt.postoffice_id = 8221
ORDER BY h.postIndex, h.POSTOFFICETYPE_ID, dayofweek, intervaltype, tFrom, tto
Just replace with the columns you want to use to decide which of the "duplicate" rows to keep. If the order doesn't matter, just remove the ORDER BY altogether.
Also, you may want to qualify all column references, since you are selecting from multiple tables.
You can use analytical function as following:
Select * from
(Select <your select column list>,
Row_number() over (partition by h.postindex, trunc(tfrom) order by tt.id desc nulls last) as rn
From <from clause>
Where <where clause>
)
Where rn = 1;
group by is not needed.
I have a query where I am getting data for some tickets.Now I need to put a where condition to get data where timediffsecs <> 0.I am unable to get the correct place to put where conditon..
Below is my code .Please help
WITH CTE
AS
(
SELECT cr.ref_num as 'TicketNumber',
isnull(requestor.last_name,'') + ', ' + isnull(requestor.first_name,'') as 'Requestor'
,ISNULL(cnt.last_name, '') + ', ' + ISNULL(cnt.first_name,'') as 'Created By'
,isnull(aeu.last_name,'') + ', ' + isnull(aeu.first_name,'') as 'Affected End User',
isnull(logagent.last_name,'') + ', ' + isnull(logagent.first_name,'') as 'Reported By'
,dbo.ConvertUnixTime (cr.open_date) as 'Open Date'
,dbo.ConvertUnixTime (cr.last_mod_dt) as 'Last Modified Date'
,dbo.ConvertUnixTime (cr.resolve_date) as 'Resolve Date'
,dbo.ConvertUnixTime (cr.close_date) as 'Close Date'
,dbo.ConvertUnixTime (act.time_stamp) as 'systime',
cr.summary as 'Summary'
,convert(varchar(max),cr.[description]) as 'Description'
,act.[action_desc] as 'System Description'
,acttype.sym as 'Activity Type'
,act.time_spent as 'Time Spent',
ROW_NUMBER() OVER(PARTITION BY cr.ref_num ORDER BY dbo.ConvertUnixTime (act.time_stamp)) RN
-- ROW_NUMBER() OVER(ORDER BY dbo.ConvertUnixTime (act.time_stamp) ) RN
-- ROW_NUMBER generated based on ORDER BY Time DESC
-- You can also add case_id or any other column to generate
--ROW_NUMBER so that the time differences can be calculate
--based on other dimension.
from call_req cr with (nolock)
LEFT OUTER JOIN ca_contact requestor with (nolock) on cr.requested_by = requestor.Contact_uuid
LEFT OUTER JOIN ca_contact aeu with (nolock) on cr.customer = aeu.Contact_uuid
LEFT OUTER JOIN ca_contact logagent with (nolock) on cr.log_agent = logagent.Contact_uuid
INNER JOIN act_log act with (nolock) on cr.persid = act.call_req_id
INNER JOIN ca_contact cnt with (nolock) on act.analyst = cnt.contact_uuid
INNER JOIN act_type acttype with (nolock) on act.[type] = acttype.code
where cr.ref_num in ('23035883',
'23038276')
)
SELECT *,
CASE
WHEN A.RN = 3 THEN
DATEDIFF(
SECOND,
(SELECT systime FROM CTE WHERE RN = 2 AND TicketNumber= A.TicketNumber),
(SELECT systime FROM CTE WHERE RN = 3 AND TicketNumber= A.TicketNumber)
-- By setting RN = 3 and 2, I am calculating
-- Time differences between ROW 3 and 2
-- You can set it to any Row number as per your requirement
)
ELSE 0
END as timediffsecs
FROM CTE A
You just need to nest the current SELECT in a subquery:
WITH cte
....
SELECT *
FROM (
YourCurrentSelect
) q
WHERE q.timediffsecs <> 0
select C.Id as candidateId,C.Name, C.Phone, Status.ResultStatusText , Status.TimeStamp, Status.notes ,
(Select count(*) from CandidateCallHistory where CandiateId = candidateId) AS numbCalls,
(SELECT SUBSTRING((SELECT ',' + Name
FROM Jobs
WHERE Id in (select value from fn_Split(c.JobIds,','))
FOR XML PATH('')),2,200000)) AS jobsList
from Candidate2 C
outer APPLY (select top 1 CH.CandiateId, CH.ResultStatusText , CH.TimeStamp , CH.notes
from CandidateCallHistory CH
where CH.CandiateId = C.Id
order by TimeStamp desc) as Status
where Status.ResultStatusText <> 'completed' and Status.ResultStatusText <> 'canceled' and c.isactive = 1
I have multiple records in the CandidateCallHistory table and seems this is causing issue with the outer apply ( i may be wrong) as it should only get the most recent record in the table since it selects top 1.
Try to add distinct in first line after select:
select distinct [...]
Using SQL Server 2012
I have seen a few threads about this topic but I can't find one that involves multiple joins in the query. I can't create a VIEW on this database so the joins are needed.
The Query
SELECT
p.Price
,s.Type
,s.Symbol
, MAX(d.Date) Maxed
FROM AdventDW.dbo.FactPrices p
INNER JOIN dbo.DimSecurityMaster s
ON s.SecurityID = p.SecurityID
INNER JOIN dbo.DimDateTime d
ON
p.DateTimeKey = d.DateTimeKey
GROUP BY p.Price ,
s.Type ,
s.Symbol
ORDER BY s.Symbol
The query works but does not produce distinct results. I am using Order by to validate the results, but it is not required once I get it working. I The result set looks like this.
Price Type Symbol Maxed
10.57 bfus *bbkd 3/31/1989
10.77 bfus *bbkd 2/28/1990
100.74049 cbus 001397AA6 8/2/2005
100.8161 cbus 001397AA6 7/21/2005
The result set I want is
Price Type Symbol Maxed
10.77 bfus *bbkd 2/28/1990
100.74049 cbus 001397AA6 8/2/2005
Here were a few other StackOverflow threads I tried but couldn't get t work with my specific query
How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?
SQL Selecting distinct rows from multiple columns based on max value in one column
If you want data for the maximum date, use row_number() rather than group by:
SELECT ts.*
FROM (SELECT p.Price, s.Type, s.Symbol, d.Date,
ROW_NUMBER() OVER (PARTITION BY s.Type, s.Symbol
ORDER BY d.Date DESC
) as seqnum
FROM AdventDW.dbo.FactPrices p INNER JOIN
dbo.DimSecurityMaster s
ON s.SecurityID = p.SecurityID INNER JOIN
dbo.DimDateTime d
ON p.DateTimeKey = d.DateTimeKey
) ts
WHERE seqnum = 1
ORDER BY s.Symbol;
You should use a derived table since you really only want to group the DateTimeKey table to get the MAX date.
SELECT p.Price ,
s.Type ,
s.Symbol ,
tmp.MaxDate
FROM AdventDW.dbo.FactPrices p
INNER JOIN dbo.DimSecurityMaster s ON s.SecurityID = p.SecurityID
INNER JOIN
( SELECT MAX(d.Date) AS MaxDate ,
d.DateTimeKey
FROM dbo.DimDateTime d
GROUP BY d.DateTimeKey ) tmp ON p.DateTimeKey = tmp.DateTimeKey
ORDER BY s.Symbol;
/*
this is your initial select which is fine because this is base from your original criteria,
I cannot ignore this so i'll keep this in-tact. Instead from here i'll create a temp
*/
SELECT
p.Price
, s.Type
, s.Symbol
, MAX(d.Date) Maxed
INTO #tmpT
FROM AdventDW.dbo.FactPrices p
INNER JOIN dbo.DimSecurityMaster s
ON s.SecurityID = p.SecurityID
INNER JOIN dbo.DimDateTime d
ON p.DateTimeKey = d.DateTimeKey
GROUP BY p.Price ,
s.Type ,
s.Symbol
ORDER BY s.Symbol
SELECT innerTable.Price, innerTable.Symbol, innerTable.Type, innerTable.Maxed
FROM (
SELECT
ROW_NUMBER () OVER (PARTITION BY t1.Symbol, t1.Type, t1.Maxed ORDER BY t1.Maxed DESC) as row
, *
FROM #tmpT AS t1
) AS innerTable
WHERE row = 1
DROP TABLE #tmpT
I have a HISTORY table that has multiple rows for the same record and I am trying to get the latest (closest to today's date) record. I am attempting to group by the closest date but am having a difficult time. Please check out the query below and advise me.
SELECT DISTINCT *
FROM
(SELECT etc.Complaint.Complaint_ID AS Complaint_ID
FROM etc.Complaint) AS Qry1
LEFT JOIN
(SELECT etc.Complaint.Complaint_ID AS Complaint_ID,
o.Action_User AS Resolved_User,
o.Action_Date AS LastActionDate
FROM etc.Complaint
LEFT OUTER JOIN etc.History as o
ON SUBSTRING(Primary_Key,15,LEN(Primary_Key) - 15) = etc.Complaint.Complaint_ID
AND TABLE_NAME = 'Resolution' AND o.Field_Name = 'Resolved_Ind'
AND New_Value = 1) AS Qry2
ON Qry1.Complaint_ID = Qry2.Complaint_ID
ORDER BY Qry1.Complaint_ID, MAX(Qry2.LastActionDate)
does this change help?
SELECT DISTINCT *
FROM
(SELECT etc.Complaint.Complaint_ID AS Complaint_ID FROM etc.Complaint) AS Qry1
LEFT JOIN
(SELECT etc.Complaint.Complaint_ID AS Complaint_ID,
o.Action_User AS Resolved_User,
o.Action_Date AS LastActionDate
FROM etc.Complaint
LEFT OUTER JOIN
(
SELECT SUBSTRING(Primary_Key,15,LEN(Primary_Key) - 15) as hist_Complaint_ID , MAX(Action_Date) as Action_Date
FROM etc.History
WHERE Field_Name = 'Resolved_Ind'
GROUP BY SUBSTRING(Primary_Key,15,LEN(Primary_Key) - 15)
) as o
ON o.hist_Complaint_ID = etc.Complaint.Complaint_ID
AND TABLE_NAME = 'Resolution' AND o.Field_Name = 'Resolved_Ind'
AND New_Value = 1) AS Qry2
ON Qry1.Complaint_ID = Qry2.Complaint_ID
ORDER BY Qry1.Complaint_ID, Qry2.LastActionDate
You can use ROW_NUMBER and a CTE to get it:
WITH cte AS (
SELECT etc.Complaint.Complaint_ID AS Complaint_ID,
o.Action_User AS Resolved_User,
o.Action_Date AS LastActionDate
row_number() over (partition by etc.Complaint.Complaint_ID order by o.Action_Date desc) AS rn
FROM etc.Complaint
LEFT OUTER JOIN etc.History as o
ON SUBSTRING(Primary_Key,15,LEN(Primary_Key) - 15) = etc.Complaint.Complaint_ID
AND TABLE_NAME = 'Resolution' AND o.Field_Name = 'Resolved_Ind'
AND New_Value = 1
)
SELECT * FROM cte
WHERE rn = 1