Limiting results in SSRS SQL query - sql

I am trying to build a report on our ticketing system using SSRS. I am bringing in fields from both an "incident body" table and an "incident details" table. What I am looking for is whether the ticket has slipped past an SLA for response to the customer.
I am checking for tickets past SLA two ways:
1) the ticket is past the SLA date and there is no detail record matching the predetermined types
2) the ticket has a detail record matching the predetermined types but it was after the SLA date
I was able to build the CTE section below but I am struggling with how to reduce the result of that to just the oldest matching row/record. A ticket should only show up once in the report.
For example:
Johnny Blogs updates a ticket using the CONTACTED_TM recordtype on 1/1/2016. The SLA was 12/31/2015. The next day (1/2/2016) he also emails the TM using the EMAILOUT recordtype. The CTE returns both these rows/records. I only want the first result.
My query code is below. I have tried using a SELECT TOP 1 in the CTE, but it just causes it to return no results.
WITH CTE (Date, [Action ID], Description, Note, [Login ID], [Seq.Group], [Incident #], ResponseDue) AS
(
SELECT Date, [Action ID], [Incident Details].Description, [Incident Details].Note, [Login ID], [Incident Details].[Seq.Group], [Incident Details].[Incident #], [Incident].[Due Date & Time:] as ResponseDue
FROM [_SMDBA_].[Incident Details]
JOIN [_SMDBA_].[Incident]
ON [Incident Details].[Incident #] = [Incident].[Incident #]
WHERE ([Action ID] = 'CONTACTED_TM' OR [Action ID] = 'TM_UNAVAILABLE' OR ([Action ID] = N'EMAILOUT' AND _SMDBA_.[Incident].[Client Email] in ([Email To Email From])))
--AND Date >= Incident.[Due Date & Time:]
)
SELECT
I.[Incident #]
,I.[Group Name]
,I.[Seq.Group] as IncidentGroupSeq
,I.[Due Date & Time:] as ResponseDue
,I.[Priority ID:]
,I.[Priority Duration]
,I.[Subject ID]
,I.[Open Date & Time] as OpenDate
,I.[Impact ID:] as Impact
,I.[Urgency ID:] as Urgency
,CTE.[Action ID]
,CTE.Description
,CTE.Note
,CTE.[Login ID]
,CTE.Date AS IncidentDetailsDate
,CTE.[Seq.Group] as DetailsGroupSeq
,_SMDBA_.CalcWorkingSeconds(1001,[Due Date & Time:],CTE.Date) as WorkingSecs
,CASE
WHEN CTE.date >= I.[Due Date & Time:] THEN 'Response was Late'
WHEN CTE.Date IS NULL THEN 'There was no response'
WHEN CTE.date <= I.[Due Date & Time:] THEN 'Met SLA'
WHEN I.[Due Date & Time:] IS NULL THEN 'No Response date set'
END AS SLAStatus
FROM [_SMDBA_].Incident I
LEFT OUTER JOIN CTE
ON CTE.[Incident #] = I.[Incident #]
WHERE
I.[Open Date & Time] >= #StartDate
AND I.[Open Date & Time] <= #EndDate
AND I.[Group Name] in (#Group)
AND I.[Impact ID:] in (#Impact)
AND I.[Urgency ID:] in (#Urgency)
AND I.[Opened Group:] = 'SERVICE DESK'

Something like this, as referenced in the comments.
WITH CTE ([Date], [Action ID], Description, Note, [Login ID], [Seq.Group], [Incident #], ResponseDue) AS
(
SELECT
[Date],
[Action ID],
[Incident Details].Description,
[Incident Details].Note,
[Login ID],
[Incident Details].[Seq.Group],
[Incident Details].[Incident #],
[Incident].[Due Date & Time:] as ResponseDue,
row_number() over (partition by [Incident Details].[Incident #] order by [Date] desc) as RN
FROM [_SMDBA_].[Incident Details]
JOIN
[_SMDBA_].[Incident]
ON [Incident Details].[Incident #] = [Incident].[Incident #]
WHERE
([Action ID] = 'CONTACTED_TM' OR [Action ID] = 'TM_UNAVAILABLE' OR
([Action ID] = N'EMAILOUT' AND _SMDBA_.[Incident].[Client Email] in ([Email To Email From])))
--AND Date >= Incident.[Due Date & Time:]
)
SELECT
I.[Incident #]
,I.[Group Name]
,I.[Seq.Group] as IncidentGroupSeq
,I.[Due Date & Time:] as ResponseDue
,I.[Priority ID:]
,I.[Priority Duration]
,I.[Subject ID]
,I.[Open Date & Time] as OpenDate
,I.[Impact ID:] as Impact
,I.[Urgency ID:] as Urgency
,CTE.[Action ID]
,CTE.Description
,CTE.Note
,CTE.[Login ID]
,CTE.Date AS IncidentDetailsDate
,CTE.[Seq.Group] as DetailsGroupSeq
,_SMDBA_.CalcWorkingSeconds(1001,[Due Date & Time:],CTE.Date) as WorkingSecs
,CASE
WHEN CTE.date >= I.[Due Date & Time:] THEN 'Response was Late'
WHEN CTE.Date IS NULL THEN 'There was no response'
WHEN CTE.date <= I.[Due Date & Time:] THEN 'Met SLA'
WHEN I.[Due Date & Time:] IS NULL THEN 'No Response date set'
END AS SLAStatus
FROM [_SMDBA_].Incident I
LEFT OUTER JOIN CTE
ON CTE.[Incident #] = I.[Incident #]
WHERE
I.[Open Date & Time] >= #StartDate
AND I.[Open Date & Time] <= #EndDate
AND I.[Group Name] in (#Group)
AND I.[Impact ID:] in (#Impact)
AND I.[Urgency ID:] in (#Urgency)
AND I.[Opened Group:] = 'SERVICE DESK'
AND CTE.RN = 1

Related

Failed to convert NVARCHAR to INT, but I'm not trying to

I get this error:
Msg 245, Level 16, State 1, Line 5
Conversion failed when converting the nvarchar value 'L NOVAK ENTERPRISES, INC' to data type int.
I've been wrestling with this query for quite a while and just can't figure out in what place that the conversion is being attempted. Using SQL Server 2017.
DECLARE #StartDate AS DateTime
DECLARE #MfgGroupCode AS Varchar(20)
SET #StartDate='2/27/2020'
SET #MfgGroupCode = 'VOLVO_NLA'
SELECT DISTCINT
CT.No_ AS [Contact Number],
CT.Name AS [Contact Name],
UAL.Time AS [Search Date],
UAL.Param1 AS [Search Part],
CT.[E-Mail] AS [Contact Email],
CT.[Phone No_] AS [Contact Phone],
CT.[Company Name] AS [Search By Customer],
(SELECT C.Name
FROM dbo.[Customer] C
WHERE C.No_ = SL.[Sell-to Customer No_]
AND C.Name <> '') AS [Sold To Customer],
SL.[Posting Date] AS [Invoice Date],
SL.[Document No_] AS [Invoice],
SL.Quantity AS [Quantity],
SL.[Unit Price] AS [Unit Price],
SL.Amount AS [Amount],
DATEDIFF(DAY, UAL.Time, SL.[Posting Date]) AS [Interval]
FROM
dbo.[User Action Log] UAL
JOIN
dbo.[User Action Types] UAT ON UAL.[User Action ID] = UAT.ID
JOIN
dbo.[Item] I ON UAL.Param1 = I.[OEM Part Number]
JOIN
dbo.[Contact] CT ON UAL.[Contact No_] = CT.No_
LEFT OUTER JOIN
dbo.[Sales Invoice Line] SL ON UAL.Param1 = SL.[OEM Part Number]
AND SL.[Posting Date] >= #StartDate
WHERE
UAT.Name IN ('SinglePartSearch', 'MultiPartSearch')
AND UAL.[MFG Group Code] = #MfgGroupCode
AND UAL.Time >= #StartDate
AND UAL.Param3 > 0
-- AND DATEDIFF(DAY, UAL.Time, SL.[Posting Date]) < 0 -- Uncomment to see Current Searches with Past Orders
-- AND DATEDIFF(DAY, UAL.Time, SL.[Posting Date]) > -1 -- Uncomment to see Searches resulting in Future Order
AND DATEDIFF(DAY, UAL.Time, SL.[Posting Date]) IS NULL -- Uncomment to See Searches with no Order
ORDER BY
Interval DESC
Thanks to all of your help and questioning, I was able to identify that the culprit is UAL.Param3.
The User Action Log table stores a variety of different "Actions" and the parameters that are affiliated with each type of action (param1, param2, param3). For one action "RequestForAccess", the "L NOVAK" value is perfectly acceptable. For this query, we're looking at the "SinglePartSearch" and "MultiPartSearch" actions, which will only contain numeric values in UAL.Param3
I replaced this line (AND UAL.Param3 > 0) with (AND ISNUMERIC(UAL.Param3) = 1 AND UAL.Param3 <> 0) in the Where clause and it is now returning the results I hoped for.
Let me know if there is a more correct way of doing this and thank you to all who contributed!

Parameter values

can anyone tell me why the following query is asking me for parameter values. It should be (or at least I want to) populating the table with data 'from' where it's pulling it from:
SELECT [BILLING_REJECTS_orig].[ORG NBR] AS BK,
[BILLING_REJECTS_orig].[ACCOUNT NUMBER] AS ACCT,
[BILLING_REJECTS_orig].APPL AS AP,
[BILLING_REJECTS_orig].[ACCOUNT NAME] AS [ACCT NAME],
[BILLING_REJECTS_orig].[TMO NAME],
IIf(Len(DatePart("m", [BILLING_REJECTS_orig]![REPORT DATE])) = 1, Year([BILLING_REJECTS_orig]![REPORT DATE]) & "-" & "0" & Month([BILLING_REJECTS_orig]![REPORT DATE]), Year([BILLING_REJECTS_orig]![REPORT DATE]) & "-" & Month([BILLING_REJECTS_orig]![REPORT DATE])) AS [ACTIVITY MONTH]
INTO Billing_Rejects_Orig
FROM dbo_BILLING_REJECTS_DEPT,
TM_Report_Date
WHERE (
((Year([Billing_Rejects_Orig]![REPORT DATE])) = Year([TM_Report_Date]![Report_Date]))
AND ((Month([Billing_Rejects_Orig]![REPORT DATE])) = Month([TM_Report_Date]![Report_Date]))
);
As #WEI_DBA points out with incorrect reference to table, consider using table aliases as shown with b and t. This cuts down SQL code and is a helpful tool in maintainability as you can then switch out the table name in FROM or JOIN clauses without a whole re-write of query, assuming same structured table.
Especially in MS Access being a default backend database (Jet/ACE) that can be switched out with other RDBMS's (SQL Server, MySQL, etc.) and occasionally used for prototyping, table aliases can help in migration between both linked and local tables.
SELECT b.[ORG NBR] AS BK,
b.[ACCOUNT NUMBER] AS ACCT,
b.APPL AS AP,
b.[ACCOUNT NAME] AS [ACCT NAME],
b.[TMO NAME],
IIf(Len(DatePart('m', b.[REPORT DATE])) = 1,
Year(b.[REPORT DATE]) & '-' & '0' & Month(b.[REPORT DATE]),
Year(b.[REPORT DATE]) & '-' & Month(b.[REPORT DATE])) AS [ACTIVITY MONTH]
INTO Billing_Rejects_Orig
FROM dbo_BILLING_REJECTS_DEPT b,
TM_Report_Date t
WHERE (
((Year(b.[REPORT DATE])) = Year(t.[Report_Date]))
AND ((Month(b.[REPORT DATE])) = Month(t.[Report_Date]))
);

DATEDIFF displaying null values

I have used DATEDIFF to distinguish between when the first unit rate was created and the posting date is when the first transaction of that item was posted.
I have the result that I need , however the DateDiff function gives me NULL values starting date for some rows.
SELECT DISTINCT b.[Entry No_] ,
a.[Starting Date],
b.[Posting Date],
b.[Item No_],
b.[Invoiced Quantity],
a.[Litre Conversion Factor],
a.[Unit Rate] ,
b.[Location Code],
a.[Excise Location],
a.[Excise Type Code],
a.[Unit Of Measure Code]
FROM [Spier Live$Value Entry] b
LEFT JOIN [Transfer Excise Tbl] a
ON a.[No_] = b.[Item No_]
AND b.[Location Code] = a.[Location Code]
AND DateDiff(y,b.[Posting Date],a.[Starting Date]) > -365 --DateDiff Year -365 for starting date
AND DateDiff(y,b.[Posting Date],a.[Starting Date]) < 0 --DateDiff Yer < 0 for posting date
WHERE b.[Posting Date] > '2013-02-26' --This is when the unit rate was entered
AND b.[Gen_ Bus_ Posting Group] IN ('LOCA','EXSA')
AND b.[Invoiced Quantity] <>0 --Removing all zero values
AND b.[Item No_] = 'F00335'
ORDER BY b.[Posting Date]
My Result
Transfer Excise Tbl This is the table I am joining on
As alex points out in the comments, you're looking for things with datediffs based on day of year, not year. Did you mean <= 0, btw? These criteria don't make sense and so probably aren't what you really want. If so, they'd cause joins to fail where you don't really want them to, leading to nulls showing for table a columns.

Access 2007 Error 3071 -report using parameters

I have a query in MS Access 2007 that pulls data from two different tables and displays in a report. This occurs after a user clicks a button on the main form, which opens a date field parameter form where the user can select two dates. From there the query runs using the two dates the user provided, or the dates are 'faked' if none are selected to fill in the dates. I'm getting a Run-time error 3071, this expression is typed incorrectly, or it is too complex to be evaluated and i'm not sure why.
I run a similar query in another database and it executes perfectly so i'm at a loss.
Query is below,
(SELECT
[Group Name],
tbGroups AS [Group Number],
Analyst,
[Account Manager],
NULL AS [SER Number],
[Received Date] AS [Corporate Recevied],
DateValue(Created) AS [Sales Submitted],
tbBAAcceptedDate AS [BA Accepted],
NULL AS [Submitted to MDSS],
NULL AS [Completed],
NULL AS [Cancelled],
DateDiff("d",[Received Date], IIf([Forms]![frmReportDateFilter].[tbToDate] = '01/01/2116', Date(), CDate([Forms]![frmReportDateFilter].[tbToDate]))) AS [Aging Days Count],
LocalID AS [ID Number]
FROM ChangeRequest
WHERE DateValue([Created]) BETWEEN CDate([Forms]![frmReportDateFilter].[tbFromDate]) AND CDate([Forms]![frmReportDateFilter].[tbToDate]))
UNION ALL (SELECT
tbGroupProgramProductName AS [Group Name],
tbGroups AS [Group Number],
cboAnalyst AS Analyst,
tbAccountManager AS [Account Manager],
tbSERNumber AS [SER Number],
tbCorpReceivedDate AS [Corporate Recevied],
tbBAReceivedDate AS [Sales Submitted],
IIf([tbBAAcceptedDate] > CDate([Forms]![frmReportDateFilter].[tbToDate]), NULL, [tbBAAcceptedDate]) AS [BA Accepted],
IIf([tbSubmittedToMDSS] > CDate([Forms]![frmReportDateFilter].[tbToDate]), NULL, [tbSubmittedToMDSS]) AS [Submitted to MDSS],
DateValue(tbCompleteDate) AS [Completed],
DateValue(tbCancelDate) AS [Cancelled],
DateDiff("d",tbCorpReceivedDate, IIf([Forms]![frmReportDateFilter].[tbToDate] = '01/01/2116', Date(), CDate([Forms]![frmReportDateFilter].[tbToDate]))) AS [Aging Days Count],
LocalID AS [ID Number]
FROM tblDD
WHERE DateValue([tbBAReceivedDate]) BETWEEN CDate([Forms]![frmReportDateFilter].[tbFromDate]) AND CDate([Forms]![frmReportDateFilter].[tbToDate]))
ORDER BY [Group Name];
Any help is greatly appreciated.
Specify the control as Date. Something like this with no CDate - and no outer parenthesis:
PARAMETERS
[Forms]![frmReportDateFilter].[tbFromDate] Date,
[Forms]![frmReportDateFilter].[tbToDate] Date;
SELECT
[Group Name],
tbGroups AS [Group Number],
Analyst,
[Account Manager],
NULL AS [SER Number],
[Received Date] AS [Corporate Recevied],
DateValue(Created) AS [Sales Submitted],
tbBAAcceptedDate AS [BA Accepted],
NULL AS [Submitted to MDSS],
NULL AS [Completed],
NULL AS [Cancelled],
DateDiff("d",[Received Date], IIf([Forms]![frmReportDateFilter].[tbToDate] = #01/01/2116#, Date(), [Forms]![frmReportDateFilter].[tbToDate])) AS [Aging Days Count],
LocalID AS [ID Number]
FROM ChangeRequest
WHERE DateValue([Created]) BETWEEN [Forms]![frmReportDateFilter].[tbFromDate] AND [Forms]![frmReportDateFilter].[tbToDate]
UNION ALL
SELECT
tbGroupProgramProductName AS [Group Name],
tbGroups AS [Group Number],
cboAnalyst AS Analyst,
tbAccountManager AS [Account Manager],
tbSERNumber AS [SER Number],
tbCorpReceivedDate AS [Corporate Recevied],
tbBAReceivedDate AS [Sales Submitted],
IIf([tbBAAcceptedDate] > [Forms]![frmReportDateFilter].[tbToDate], NULL, [tbBAAcceptedDate]) AS [BA Accepted],
IIf([tbSubmittedToMDSS] > [Forms]![frmReportDateFilter].[tbToDate], NULL, [tbSubmittedToMDSS]) AS [Submitted to MDSS],
DateValue(tbCompleteDate) AS [Completed],
DateValue(tbCancelDate) AS [Cancelled],
DateDiff("d",tbCorpReceivedDate, IIf([Forms]![frmReportDateFilter].[tbToDate] = #01/01/2116#, Date(), [Forms]![frmReportDateFilter].[tbToDate])) AS [Aging Days Count],
LocalID AS [ID Number]
FROM tblDD
WHERE DateValue([tbBAReceivedDate]) BETWEEN [Forms]![frmReportDateFilter].[tbFromDate] AND [Forms]![frmReportDateFilter].[tbToDate]
ORDER BY [Group Name];

Union Subquery produces Results Non-Unioned Subquery doesn't

I'm using Access 2010 and i'm having a very strange query result.
I've created a query that includes a union subquery that produces results. I've also created a query that has a non-unioned subquery that doesn't produce any records. It's very strange because the union subquery is the non-unioned subquery twice.
Non-Unioned Subquery:
SELECT NVP, [NVP NAME], MIN([CURRENT PERIOD]) AS [MIN PERIOD], [BASE PERIOD]
FROM AGGDATA
GROUP BY [NVP NAME],NVP,[BASE PERIOD]
Unioned Subquery:
SELECT NVP, [NVP NAME], MIN([CURRENT PERIOD]) AS [MIN PERIOD], [BASE PERIOD]
FROM AGGDATA
GROUP BY [NVP NAME],NVP,[BASE PERIOD]
UNION
SELECT NVP, [NVP NAME], MIN([CURRENT PERIOD]) AS [MIN PERIOD], [BASE PERIOD]
FROM AGGDATA
GROUP BY [NVP NAME],NVP,[BASE PERIOD]
Here is the whole Query:
SELECT sub.NVP,sub.[NVP NAME], SUB.[MIN PERIOD], SUB.[BASE PERIOD], TT.[ACTIVE PERIODS]
FROM
(SELECT AGGD.NVP, AGGD.[NVP NAME], MIN(AGGD.[CURRENT PERIOD]) AS [MIN PERIOD], [BASE PERIOD]
FROM AGGDATA AGGD
GROUP BY AGGD.[NVP NAME],AGGD.NVP,[BASE PERIOD]
UNION
SELECT AGGD.NVP, AGGD.[NVP NAME], MIN(AGGD.[CURRENT PERIOD]) AS [MIN PERIOD], [BASE PERIOD]
FROM AGGDATA AGGD
GROUP BY AGGD.[NVP NAME],AGGD.NVP,[BASE PERIOD])
AS SUB
INNER JOIN
(SELECT SUB.NVP,
SUB.[BASE PERIOD],
COUNT([CURRENT PERIOD]) AS [ACTIVE PERIODS]
FROM
(SELECT DISTINCT NVP, [BASE PERIOD], [CURRENT PERIOD]
FROM AGGDATA)
AS SUB
GROUP BY SUB.NVP, SUB.[BASE PERIOD]
having COUNT([CURRENT PERIOD]) < 10)
AS TT
ON SUB.[BASE PERIOD] = TT.[BASE PERIOD] AND SUB.NVP = TT.NVP
WHERE SUB.[MIN PERIOD] > TT.[BASE PERIOD]
Does anyone know why the Union subquery works but the non-unioned subquery doesn't?
EDIT: The two subqueries do produce the same results, the issue is with the whole query.
Thank you!
I think you have some issues with your parentheses and aliases. Try this code instead:
SELECT
mn.NVP,[NVP NAME], [MIN PERIOD], mn.[BASE PERIOD], TT.[ACTIVE PERIODS]
FROM
(SELECT
[NVP NAME],NVP,[BASE PERIOD], MIN([CURRENT PERIOD]) AS [MIN PERIOD]
FROM
AGGDATA
GROUP BY
[NVP NAME],NVP,[BASE PERIOD]) AS mn INNER JOIN
(SELECT
NVP,
[BASE PERIOD],
COUNT([CURRENT PERIOD]) AS [ACTIVE PERIODS]
FROM
(SELECT DISTINCT
NVP, [BASE PERIOD], [CURRENT PERIOD]
FROM
AGGDATA) AS a
GROUP BY
NVP, [BASE PERIOD]
HAVING
COUNT([CURRENT PERIOD]) < 10) AS TT ON
mn.[BASE PERIOD] = TT.[BASE PERIOD] AND
mn.NVP = TT.NVP
WHERE
mn.[MIN PERIOD] > TT.[BASE PERIOD]