obtain an average of days an issue is open - sql

I have a table with a 'call open date' column (actual_log_date) which I convert, using
convert(char(10), actual_log_date, 103) 'Call Logged'
to show calls logged on 01/02/2012 for example.
There is also a close time column (close_time) for which I run the same convert,
convert(char(10), close_time, 103) 'Call Closed'
to show calls closed on 12/02/2012.
Now, I need to produce a script to get the average number of days calls have been open. I can run
(select datediff(dd, c.actual_log_date, c.close_time)) as 'Days Open'
to create the column which shows the call was open for 12 days or whatever, but now need to count all the records and obtain the average sum at the end of the results, which is where I am stuck!
I forgot to say I can't create a temp table as I only have read only rights.
Sorry, I'm new here so not sure on the protocol but here is the script if it's easier to answer seeing what I'm working with;
select
convert(char(10),actual_log_date,103) 'Call Logged',
call_number 'Call #',
short_problem 'Issue Description',
Customer = (select surname + ', ' + first_name from i.ar_user_attributes where ref = user_ref ),
Officer = (select surname + ', ' + first_name from i.su_help_centre where ref = resolve_officer),
Department = (select name from i.su_support_group where ref = resolve_group),
convert(char(10),close_time,103) 'Closed',
(select datediff(hh,c.actual_log_date,c.close_time)) as 'Hours Open',
(select datediff(dd,c.actual_log_date,c.close_time)) as 'Days Open'
from
i.cl_call_logging c
where
c.resolve_time between
convert(datetime,convert(varchar,month(dateadd(m,-1,getdate()))) + '/01/' + convert(varchar,year(dateadd(m,-1,getdate())))) and
convert(datetime,convert(varchar,month(getdate())) + '/01/' + convert(varchar,year(getdate())))
and c.resolve_group in ('48', '60')
Thanks again!

You can use a with query, like this:
insert into #temp (CallOpen, CallClosed)
values
('2012-01-02', '2012-02-12'),
('2012-01-05', '2012-02-12'),
('2012-01-07', '2012-02-05'),
('2012-01-14', '2012-02-03'),
('2012-02-10', '2012-03-15')
;with T1 as
(
select
CallOpen,
CallClosed,
DATEDIFF(dd, callopen, callclosed) as DaysOpen
from #temp
)
select AVG(daysopen) from T1
Using your full script, try this:
;with T1 as
(
select
convert(char(10),actual_log_date,103) 'Call Logged',
call_number 'Call #',
short_problem 'Issue Description',
Customer = (select surname + ', ' + first_name from i.ar_user_attributes where ref = user_ref ),
Officer = (select surname + ', ' + first_name from i.su_help_centre where ref = resolve_officer),
Department = (select name from i.su_support_group where ref = resolve_group),
convert(char(10),close_time,103) 'Closed',
(select datediff(hh,c.actual_log_date,c.close_time)) as 'Hours Open',
(select datediff(dd,c.actual_log_date,c.close_time)) as 'Days Open'
from #cl_call_logging c
where
c.resolve_time between
convert(datetime,convert(varchar,month(dateadd(m,-1,getdate()))) + '/01/' + convert(varchar,year(dateadd(m,-1,getdate())))) and
convert(datetime,convert(varchar,month(getdate())) + '/01/' + convert(varchar,year(getdate())))
and c.resolve_group in ('48', '60')
)
select AVG([Days Open]) from T1

Related

Query Filter based on condition

I have this query (SQL Server 2019) and I actually wanted to add a filter to it to show only items where IssueStatusID = 1 (This column is based on int Data Type)
Can anyone help with this or point me in the right direction?
SELECT ID,
STRING_AGG(TRY_CONVERT(varchar, Issue#, 101) + ': ' + Notes + CHAR(13) + CHAR(10) + CHAR(13), CHAR(10)) WITHIN GROUP (ORDER BY Issue# DESC) AS IssueNotes
FROM (SELECT DISTINCT
ac4.ID,
nd.Notes,
nd.Issue#,
nd.IssueStatusID
FROM dbo.IssueTracking AS nd
INNER JOIN dbo.StatusUpdates AS ac4 ON ac4.ID = nd.ReleaseTrackerID) AS vNotes
GROUP BY ID;
Add the WHERE clause as shown below. The WHERE clause limits the data being returned.
SELECT ID,
STRING_AGG(TRY_CONVERT(varchar, Issue#, 101) + ': ' + Notes + CHAR(13) + CHAR(10) + CHAR(13), CHAR(10)) WITHIN GROUP (ORDER BY Issue# DESC) AS IssueNotes
FROM (SELECT DISTINCT
ac4.ID,
nd.Notes,
nd.Issue#,
nd.IssueStatusID
FROM dbo.IssueTracking AS nd
INNER JOIN dbo.StatusUpdates AS ac4 ON ac4.ID = nd.ReleaseTrackerID
WHERE nd.IssueStatusID = 1
) AS vNotes
GROUP BY ID;

Putting SQL record values in a single row

SQL isn't my expertise but, how do I write a SQL query that takes values from two different records and put them in one row? For example, I did a query on this EmployeeId, and I need the output values specifically from the Vacation_Type column for Adjust on 2016-07-01 (if it exists) and the Forward value from date 2016-08-01 (exists for every employee) ? Desired output would be:
26, SL, 547.58, -37.42
Not every employee would have an Adjust record, they have an Adjust when they are over the sick leave cap... and not everyone is over the cap. Thanks!
select
EV.EmployeeID,
EV.Vacation_Kind,
stuff( ( select ', ' + convert(varchar(30), EV1.Value) from EmployeeVacations EV1
where EV1.EmployeeID = EV.EmployeeID and EV1.Vacation_Kind = EV.Vacation_Kind
and EV1.VacationType in ('Adjust','Forward') and EV1.CreationDate IN (EV.CreationDate, dateadd(month, datediff(month, 0, dateadd(month, 1, EV.CreationDate)), 0))
for xml path('')
), 1, 1, '')
from
EmployeeVacations EV
where
EV.EmployeeID = 26 and EV.Vacation_Kind = 'SL'and VacationType = 'Adjust'
group by
EV.EmployeeID, EV.Vacation_Kind, EV.CreationDate
Since the 'Adjust' record isn't guaranteed to be there, you can use a LEFT OUTER JOIN. The following queries all employees, but you can uncomment the two lines if you really only want employee 26...
SELECT
CAST(fwd.EmployeeId AS varchar) + ', ' +
fwd.Vacation_Kind + ', ' +
CAST(fwd.[Value] as varchar) +
CASE WHEN adj.Value IS NULL THEN '' ELSE ', ' + CAST(adj.Value AS varchar) END
FROM
#employeeVacations fwd
LEFT OUTER JOIN #employeeVacations adj ON
adj.EmployeeId = fwd.EmployeeId)
AND
adj.Vacation_Kind = 'SL')
AND
adj.Vacation_Type = 'Adjust'
AND
adj.CreationDate = '2016-07-01'
WHERE
--fwd.EmployeeId = 26
--AND
fwd.Vacation_Kind = 'SL'
AND
fwd.Vacation_Type = 'Forward'
AND
fwd.CreationDate = '2016-08-01'

How do you transpose rows into columns in a SQL query

I have this output:
Contact_Type Category_Type Category_Count
---------------------------------------------------
Window Admissions 1775
Window Financial Aid 17377
Window Miscellaneous 2720
Window Student Financials 14039
Phone Admissions 5758
Phone Financial Aid 10048
Phone Miscellaneous 4497
Phone Registration 11
Phone Student Financials 4857
and this is my query:
SELECT
Contact_Type, Category_Type1, Category_Type2, Category_Type3,
Category_Type4, Category_Type5
FROM
(SELECT
CASE
WHEN event.contact_type = 0 THEN 'Window'
WHEN event.contact_type = 1 THEN 'Phone'
END AS Contact_Type,
cat.category_type AS Category_Type,
COUNT(ec.category_id) AS Category_Count,
'Category_Type' + CAST(ROW_NUMBER() OVER (PARTITION BY Contact_Type
ORDER BY Contact_Type) AS varchar(20)) AS ColumnSequence
FROM
yLines.ylines_event AS Event
JOIN
ylines.ylines_event_category AS ec ON ec.event_id = event.event_id
JOIN
ylines.ylines_category AS cat ON ec.category_id = cat.category_id
WHERE /*event.contact_type = '0' AND*/
CAST(FORMAT(event.event_date_time, 'yyyy') AS int) BETWEEN 2014 AND dateadd(year, 1, event.event_date_time)
GROUP BY
Category_Type, Contact_Type) a
PIVOT
(MAX(Contact_Type)
FOR ColumnSequence IN (Category_Type1, Category_Type2, Category_Type3,
Category_Type4, Category_Type5)) as piv;
If I run this it gives me an error:
Msg 207, Level 16, State 1, Line 1
Invalid column name 'Contact_Type'
and I can't seem to fix this. I am trying to transpose it so I see two rows only with 'Windows' and 'Phone' and the five Category Types transposed as five columns with the count in each. I am writing T-SQL statements. Please help!
I would try do it in dynamic
; WITH [CONTACT]
AS (
SELECT *
FROM (
VALUES
('Window', 'Admissions ', ' 1775')
, ('Window', 'Financial Aid ', '17377')
, ('Window', 'Miscellaneous ', ' 2720')
, ('Window', 'Student Financials', '14039')
, ('Phone ', 'Admissions ', ' 5758')
, ('Phone ', 'Financial Aid ', '10048')
, ('Phone ', 'Miscellaneous ', ' 4497')
, ('Phone ', 'Registration ', ' 11')
, ('Phone ', 'Student Financials', ' 4857')
) X ([Contact_Type], [Category_Type], [Category_Count])
)
SELECT *
INTO #TEMP_PIVOT
FROM [CONTACT]
DECLARE #TYPE VARCHAR(MAX)
SET #TYPE = STUFF(
(SELECT DISTINCT ', ' + QUOTENAME(RTRIM(LTRIM([CATEGORY_TYPE])))
FROM #TEMP_PIVOT
FOR XML PATH('')
)
, 1, 1, '')
DECLARE #SQL VARCHAR(MAX)
SET #SQL = ' SELECT [CONTACT_TYPE] '
+ ' , ' + #TYPE
+ ' FROM #TEMP_PIVOT '
+ ' PIVOT ( '
+ ' MAX([CATEGORY_COUNT]) '
+ ' FOR [CATEGORY_TYPE] IN (' + #TYPE + ')'
+ ' ) P '
EXECUTE (#SQL)
In the group by clause you say
`group by Category_Type, Contact_Type`
However, you have defined a calculated column as contact_type which is not available in the group by clause. You should use
GROUP BY Category_Type, -- Contact_Type
case
when event.contact_type=0 then 'Window'
when event.contact_type=1 then 'Phone'
end
It is a better approach to name your calculated columns different than the columns in any of your tables.
Use case statements for pivoting:
SELECT CONTACT_TYPE,
SUM(CASE WHEN CATEGORY_TYPE='Admissions' THEN CATEGORY_COUNT END) ADMISSIONS,
SUM(CASE WHEN CATEGORY_TYPE='Financial Aid' THEN CATEGORY_COUNT END) FINANCIAL_AID,
SUM(CASE WHEN CATEGORY_TYPE='Miscellaneous' THEN CATEGORY_COUNT END) MISCELLANEOUS,
SUM(CASE WHEN CATEGORY_TYPE='Student Financials' THEN CATEGORY_COUNT END) STUDENT_FINANCIALS,
SUM(CASE WHEN CATEGORY_TYPE='Registration' THEN CATEGORY_COUNT END) REGISTRATION
FROM TEST_3 GROUP BY CONTACT_TYPE;
Output:
CONTACT_TYPE ADMISSIONS FINANCIAL_AID MISCELLANEOUS STUDENT_FINANCIALS REGISTRATION
Phone 5758 10048 4497 4857 11
Window 1775 17377 2720 14039 null

Add Int Column Values Similar To Count

I have a data structure similiar to:
Person | Counter
Mary 1
Mary 2
John 5
John 6
I am trying to Group By on the Person column, and add up the values for the counter, for each person. Meaning, I am trying to return:
Person - Mary - Has 3 Counters
Person - John - Has 11 Counters
This is my current effort, however it is not working:
SELECT ('Person - '+ ISNULL(NULLIF([Person],''),'NOT ASSIGNED') + 'Has') as Name,
COUNT(*) Match, (SELECT COUNT(*) + 'Counters' FROM [MyTable] ) Total
FROM [MyTable]
Here you go:
DECLARE #DATA TABLE (Person VARCHAR(25), [Counter] INT)
INSERT INTO #DATA
SELECT 'Mary',1 UNION
SELECT 'Mary',2 UNION
SELECT 'John',5 UNION
SELECT 'John',6
SELECT 'Person - ' + ISNULL(Person,'Not Assigned') + ' - has ' + CAST(SUM([Counter]) AS VARCHAR) + ' counters'
from #DATA
GROUP BY Person
What you want is a group by clause just as you stated, so something based on this:
SELECT Person, SUM(Counter)
FROM MyTable
GROUP BY Person
I didn't include the extra text from your original query to make it a bit more compact.
Cheruvian's answer might be what you want, I can't tell exactly by your example, here is what I came up with just in case.
SELECT 'Person - ' + ISNULL(NULLIF(Person, ''), 'NOT ASSIGNED') + ' - Has ' + SUM(Counter) + ' Counters' As ReportOutput
FROM MyTable
GROUP BY Person
ORDER BY Person;
You should be using an aggregate function for this.
SELECT ('Person - '+ ISNULL(NULLIF([Person],''),'NOT ASSIGNED') + 'Has') as Name,
COUNT(*) As Match,
Sum(Counter) As Count
FROM [MyTable]
Group By Person
You were also missing an As in the second line. The Sum Aggregate function will Sum all of the values for each group, in this case your counter.
I would do this using a GROUP BY in a subselect, and then build the string using the results. Something like this:
SELECT ('Person - '+ myperson + ' Has ' + CAST(mycount AS VARCHAR) + ' Counters')
FROM (SELECT ISNULL(NULLIF([Person],''),'NOT ASSIGNED') myperson, sum(counter) mycount
FROM [MyTable]
GROUP BY ISNULL(NULLIF([Person],''),'NOT ASSIGNED')) a

SQL Stored Procedure - replace a result column with value from existing table column

I'm having trouble figuring out how to replace a value on a stored procedure result based on values from another table. I have a table [LOG] that is formatted as such:
TIME STAMP, TAG, DESCRIPTION, EVENTCODE, SUBEVENTCODE
30-Aug-2013 10:14:10, TAG X, HI TEMP FAULT, 3, 16
30-Aug-2013 10:12:10, TAG Y, HI PRESS FAULT, 3, 16
...
And another table [EVENTS] which basically describes what the EVENTCODE is:
EVENT, DESCRIPTION
1, FAULT
2, LOGIC
3, ALARM
I would like to have the stored procedure retrieve 2000 entries (rows) of the 1st table and, instead of showing EVENTCODE as a number, display the description contained in the 2nd table on the result.
e.g:
TIME STAMP, TAG, DESCRIPTION, EVENTCODE, SUBEVENTCODE
30-Aug-2013 10:14:10, TAG X, HI TEMP FAULT, ALARM, 16
Reason is I have another software that interacts with the result of the stored procedure, and wouldn't like to create another table to hold these results within the database.
Here is what the stored procedure looks like so far:
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[Get2kEvents]
AS
BEGIN
SELECT TOP 2000 CAST(datepart(day,TIME_STAMP) as char(2)) + '-' +
CAST(datename(month,TIME_STAMP) as char(3)) + '-' +
CAST(datepart(year,TIME_STAMP) as char(4))+ ' ' + CONVERT(varchar,TIME_STAMP,108)
as 'TIME STAMP',
[TAG],
[DESCRIPTION],
[EVENTCODE],
[SUBEVENTCODE]
FROM [Arc_DB].[dbo].[LOG]
ORDER BY TIME_STAMP DESC
END
GO
I appreciate your assistance. Sorry if this is too basic, but I wasn't able to figure out a solution for this while browsing this and other websites.
Cheers.
TM
You want to join the two tables. ie:
SELECT TOP 2000 CAST(datepart(day,TIME_STAMP) as char(2)) + '-' +
CAST(datename(month,TIME_STAMP) as char(3)) + '-' +
CAST(datepart(year,TIME_STAMP) as char(4))+ ' ' + CONVERT(varchar,TIME_STAMP,108)
as 'TIME STAMP',
[TAG],
[DESCRIPTION],
Events.Description,
[SUBEVENTCODE]
FROM [Arc_DB].[dbo].[LOG]
inner join events on log.eventcode = events.event
ORDER BY TIME_STAMP DESC
Use a JOIN:
SELECT TOP 2000 CAST(datepart(day,TIME_STAMP) as char(2)) + '-' +
CAST(datename(month,TIME_STAMP) as char(3)) + '-' +
CAST(datepart(year,TIME_STAMP) as char(4))+ ' ' + CONVERT(varchar,TIME_STAMP,108)
as 'TIME STAMP',
[TAG],
L.[DESCRIPTION],
E.[DESCRIPTION],
[SUBEVENTCODE]
FROM [Arc_DB].[dbo].[LOG] L
INNER JOIN [Arc_DB].[dbo].[EVENTS] E ON E.EVENT = L.EVENTCODE
ORDER BY TIME_STAMP DESC
I would use a left join and check for missing codes:
SELECT TOP 2000 CAST(datepart(day,TIME_STAMP) as char(2)) + '-' +
CAST(datename(month,TIME_STAMP) as char(3)) + '-' +
CAST(datepart(year,TIME_STAMP) as char(4))+ ' ' + CONVERT(varchar,TIME_STAMP,108)
as 'TIME STAMP',
[TAG],
[DESCRIPTION],
CASE WHEN EVENTS.DESCRIPTION IS NULL
THEN 'UNKNOWN CODE '+CAST(LOG.EVENTCODE AS VARCHAR(20))
ELSE EVENTS.DESCRIPTION
END AS [Event Type],
[EVENTCODE],
[SUBEVENTCODE]
FROM LOG
LEFT JOIN EVENTS ON EVENTS.EVENT= LOG.EVENTCODE
ORDER BY TIME_STAMP DESC