Converting an AVG from HH-MM-SS to Minutes - sql

I have a query like this:
with first_reply as (
select
t.id as ticket_id,
tc.created,
row_number() over(partition by tc.ticket_id order by tc.created) as rn
from ticket t
inner join ticket_comment tc
on t.id = tc.ticket_id
inner join user u
on u.id = tc.user_id
where u.role in ('employee')
order by tc.ticket_id, tc.created)
select
avg(far.created-t.created_at)
from ticket t
inner join first_agent_reply far
on far.ticket_id = t.id
join ticket_tag tt
ON tt.ticket_id = t.id
AND rn = 1
It gives me an avg time in the format of 22:23:56.973609
How can I convert this to showing me just total minutes? Ie: 1920 Mins
Thank you!

If you're using sql server please use the below function,
DATEDIFF(minute, 0, CONVERT(TIME,'22:23:56.973609'))
Probably the last part of your code will be like this,
select
DATEDIFF(minute, 0, CONVERT(TIME,avg(far.created-t.created_at)))
from ticket t
The answer you get here is 1343

Related

Count with row_number function SQL CTE

I have the below CTEs that work perfectly, but I want to count the "cl.memb_dim_id" by "cl.post_date" but I am not sure how to do that? When adding in the count function I get an error that highlights the ' row number' so I am assuming I cant have both order and group together ????
WITH
DATES AS
(
select to_date('01-jan-2017') as startdate,to_date('02-jan-2017') as enddate
from dual
),
Claims as (select distinct
cl.memb_dim_id,
row_number () over (partition by cl.Claim_number order by cl.post_date desc) as uniquerow,
cl.Claim_number,
cl.post_date,
ct.claim_type,
ap.claim_status_desc,
dc.company_desc,
dff.io_flag_desc,
pr.product_desc,
cl.prov_dim_id,
cl.prov_type_dim_id
from dw.fact_claim cl
inner join dates d
on 1=1
and cl.post_date >= d.startdate
and cl.post_date <= d.enddate
and cl.provider_par_dim_id in ('2')
and cl.processing_status_dim_id = '1'
and cl.company_dim_id in ('581','585','586','589','590','591','588','592','594','601','602','603','606','596','598','597','579','599','578','577','573','574','576','575')
left join dw.DIM_CLAIM_STATUS ap
on cl.claim_status_dim_id = ap.claim_status_dim_id
left join dw.dim_claim_type ct
on cl.claim_type_dim_id = ct.claim_type_dim_id
and cl.claim_type_dim_id in ('1','2','6','7')
left join dw.DIM_COMPANY dc
on cl.company_dim_id = dc.company_dim_id
left join dw.DIM_IO_FLAG dff
on cl.io_flag_dim_id = dff.io_flag_dim_id
left join dw.dim_product pr
on cl.product_dim_id = pr.product_dim_id
)
Select * from claims where uniquerow ='1'
First, does this work?
count(cl.memb_dim_id) over (partition by cl.Claim_number, cl.post_date) as cnt,
Second, it is strange to be using analytic functions with select distinct.

SQL Server Delete Rows from Table leaving the record with the Max CreationDate

I want to delete the older records from the table based on creation date,leaving the latest one
attempted SQL,but did not work.
SELECT *
--DELETE L
FROM ItemPriceListMap L
LEFT JOIN (
SELECT ItemPriceListUID3,MAX(CAST(CreationDate as DATE)) MaxDate
FROM ItemPriceListMap
GROUP BY ItemPriceListUID3
)M ON L.ItemPriceListUID3 = M.ItemPriceListUID3 AND CAST(L.CreationDate as DATE) = M.MaxDate
WHERE M.ItemPriceListUID3 IS NULL
The view of the mapping
SELECT I.Description,ipl.UnitListPrice1,iplmp.VatMRP,iplmp.CreationDate FROM ItemPriceListMap iplmp
INNER JOIN ItemPriceList ipl ON iplmp.ItemPriceListUID3 = ipl.UID
INNER JOIN Item i ON ipl.ItemUID = i.UID
ORDER BY I.Description,iplmp.CreationDate
EDIT:
More Sample Data
Using this SQL
SELECT I.Description,iplmp.ItemPriceListUID3,iplmp.CreationDate FROM ItemPriceListMap iplmp
INNER JOIN ItemPriceList ipl ON iplmp.ItemPriceListUID3 = ipl.UID
INNER JOIN Item i ON ipl.ItemUID = i.UID
ORDER BY I.Description,iplmp.CreationDate
so after I execute the delete command the highlighted row should be left in the table(yellow),highlighted in blue is the same Item
TRY THIS: You can use your own query by doing some simple changes as below, you have to join as <> with the max date so it will not delete that record, only delete others which matches ItemPriceListUID3 and <> MaxDate
SELECT *
--DELETE L
FROM ItemPriceListMap L
INNER JOIN (SELECT MAX(CAST(CreationDate as DATE)) MaxDate
FROM ItemPriceListMap
) M ON CAST(L.CreationDate as DATE) <> M.MaxDate
Try this :
DELETE L
FROM ItemPriceListMap L
WHERE CreationDate <> (SELECT MAX(CreationDate) MaxDate
FROM ItemPriceListMap LL
WHERE L.ItemPriceListUID3 = LL.ItemPriceListUID3)
Note : Take backup of your data first.
Use a CTE and a row_number
with CTE as
(
select a1.*, row_number() over(
partition by ItemPriceListUID3 -- remove this if you don't need the grouping
order by CreationDate desc) as R_ORD
from ItemPriceListMap a1
)
delete
from CTE
where R_ORD > 1

How do I find the oldest date in Group

I have a table where I need to get the oldest date from a group and be able to return all rows. I'm finding it difficult since I need to return the system_id field.
AssignedProfsHistory MatterID EffectiveDate
1 33434-3344 08/22/2005
2 33434-3344 07/12/2004
3 33434-3344 07/12/2004
4 21122-323 12/05/2007
5 43332-986 10/18/2014
6 43332-986 03/23/2013
So in this example, the rows for systemid 2 & 3 should return because they are tied for earliest date. The row for systemid 4 should return and systemid 6 should be returned.
This is what I have so far. Because I need to include the systemid(AssignedProfHistory) I'm not getting the results I need.
SELECT aph.AssignedProfsHistory,
m.MatterID,
Min(aph.EffectiveDate) as 'EffectiveDate'
from AssignedProfsHistory aph
INNER JOIN Matters m
ON aph.Matters = m.Matters
WHERE aph.AssignedType = 'Originating'
Group by m.matters,m.matterid,aph.assignedprofshistory
order by m.MatterID
Any idea how to get the results I need?
Thank you in advance.
select AssignedProfsHistory, MatterID, EffectiveDate
from (
SELECT
aph.AssignedProfsHistory,
m.MatterID,
aph.EffectiveDate,
row_number() over(partition by m.MatterID order by aph.EffectiveDate) as rn
from AssignedProfsHistory aph
INNER JOIN Matters m ON aph.Matters = m.Matters
WHERE aph.AssignedType = 'Originating'
) t
where rn = 1;
You can use the row_number window function to assign row numbers to dates for each matterid. Because the ordering is based on the ascending EffectiveDate, rows with the oldest date get assigned 1 and you select those.
If a matterid can have multiple rows with the oldest dates, you can use rank or dense_rank to get all the rows for the oldest date.
Since you want to keep the ties, I'd do it like this:
SELECT t2.AssignedProfsHistory, m.MatterID, t2.EffectiveDate
FROM (
SELECT MatterID, MIN(EffectiveDate) med
FROM AssignedProfsHistory
WHERE AssignedType = 'Originating'
GROUP BY MatterID
) t1
INNER JOIN AssignedProfsHistory t2 ON t2.MatterID = t1.MatterID
and t2.EffectiveDate = t1.med and t2.AssignedType = 'Originating'
INNER JOIN Matters m on m.Matters = t2.Matters
ORDER BY m.MatterId
Here is an SQLFiddle without the Matters table that demonstrates it can work, no windowing functions or CTE required, though a CTE would allow you to avoid repeating the AssignedType='Originating' condition.
this should get you what you need
with cte as (
SELECT aph.AssignedProfsHistory,
m.MatterID,
aph.EffectiveDate as 'EffectiveDate'
from AssignedProfsHistory aph
INNER JOIN Matters m
ON aph.Matters = m.Matters
WHERE aph.AssignedType = 'Originating'
Group by m.matters,m.matterid,aph.assignedprofshistory
)
select
AssignedProfsHistory,
MatterID,
EffectiveDate
from
cte
join (
select
min(EffectiveDate) min_effectivedate,
MatterID
from
cte
group by
MatterID
) b on cte.EffectiveDate = b.min_effectivedate and
cte.MatterID = b.MatterID
order by AssignedProfsHistory
First take the older date and then join it with your table.
WITH OlderAPH AS (
SELECT
AssignedProfsHistory,
Matters,
MIN(EffectiveDate) OlderDate
FROM AssignedProfsHistory
WHERE AssignedType = 'Originating'
GROUP BY Matters, AssignedProfsHistory )
SELECT
O.AssignedProfsHistory, M.MatterID, O.OlderDate
FROM OlderAPH O
INNER JOIN Matters M ON O.Matters = M.Matters
ORDER BY M.MatterID

Use having to find avg

I'm currently writing an SQL statement that requires me to list the workers who have a greater hours worked than the average.
Here is my current code:
Select T.TotalCandy,Sum(T.Amountofcandy) "Total Candy"
From ToralChocolate
Inner Join Ompaloompa O
On T.CandyNo = O.CandyNo and T.BoatNO = O.BoatNo
Inner Join Transport TR
On TR.Transport = T.Transport
Having Sum(T.AmountofCandy) > (Select Avg(AmountofCandy) from TotalChocolate)
Group By T.TotalCandy
Order By 1;
I run into my problem at the subquery in the having statement as I'm comparing it to the average hours worked not the average of the SUM of hours worked!
Any help would be appreciated.
Select W.WrkName,Sum(TI.HrsWorked) "Total Hours"
From Timelog TI
Inner Join Allocation A
On TI.WrkID = A.WrkID and TI.TaskID = A.TaskID
Inner Join Worker W
On TI.WrkID = W.WrkID
Group By W.WrkName
Having Sum(TI.HrsWorked) >
(Select Avg(HrsWorked)
From
(Select WrkID, SUM(HrsWorked) As HrsWorked
From Timelog
Group By WrkID)
)
Order By 1;
Have you tried something like that?
Select W.WrkName,Sum(TI.HrsWorked) "Total Hours"
From Timelog TI
Inner Join Allocation A
On TI.WrkID = A.WrkID and TI.TaskID = A.TaskID
Inner Join Worker W
On TI.WrkID = W.WrkID
Group By W.WrkName
Having Sum(TI.HrsWorked) > (Select Avg(HrsWorked) from Timelog)
Order By 1;
HAVING CLAUSE AFTER GROUP!

SQL Query to return last value from a number of tags

I hope you might be able to help. I'm a novice at SQL so this one is starting to bug me.
Currently I am collecting data every day for a Meter Name. This data is currently being logged in a table with the columns TimeStamp, Name, Value. However I would like to create a query which will only return the most recent (last) value recorded against each Name in the table.
I've built this query so far but the Top 1 syntax doesn't seem to be what I need.
SELECT Top 1 (DataLog.Timestamp), MeterTags.Name, DataLog.Value
FROM Meters
INNER JOIN MeterTags
ON Meters.MeterId = MeterTags.MeterId
INNER JOIN DataLog
ON MeterTags.MeterTagId = DataLog.MeterTagId
WHERE Meters.MeterTypeId = 8
GROUP By MeterTags.Name, DataLog.Timestamp
Any advice you could give would be appreciated.
Thanks in advance.
You can use ROW_NUMBER to give each record a rownumber (resetting to 0 for each MeterTags.Name) then just select the first for each name:
WITH CTE AS
( SELECT DataLog.Timestamp,
MeterTags.Name,
DataLog.Value,
RowNumber = ROW_NUMBER() OVER(PARTITION BY MeterTags.Name
ORDER BY DataLog.TimeStamp DESC)
FROM Meters
INNER JOIN MeterTags
ON Meters.MeterId = MeterTags.MeterId
INNER JOIN DataLog
ON MeterTags.MeterTagId = DataLog.MeterTagId
WHERE Meters.MeterTypeId = 8
)
SELECT CTE.Timestamp,
CTE.Name,
CTE.Value
FROM CTE
WHERE CTE.RowNumber = 1;
Another solution is to use the TOP 1 inside an APPLY:
SELECT DataLog.Timestamp,
MeterTags.Name,
DataLog.Value
FROM Meters
INNER JOIN MeterTags
ON Meters.MeterId = MeterTags.MeterId
CROSS APPLY
( SELECT TOP 1 TimeStamp, Value
FROM DataLog
WHERE MeterTags.MeterTagId = DataLog.MeterTagId
ORDER BY TimeStamp DESC
) DataLog
WHERE Meters.MeterTypeId = 8;
Try below query
select Timestamp,Name,Value
from
(
SELECT (DataLog.Timestamp), MeterTags.Name, DataLog.Value,rownum,ROW_NUMBER() OVER
(PARTITION BY MeterTags.Name ORDER BY DataLog.Timestamp desc) AS rownum FROM Meters
INNER JOIN MeterTags
ON Meters.MeterId = MeterTags.MeterId
INNER JOIN DataLog
ON MeterTags.MeterTagId = DataLog.MeterTagId
)data
where rownum=1