SQL - condition on a timestampdiff - sql

I would like to get the average time of solution time for tickets
from state 'billet ouvert' to state 'résolu'.
Table Sample
The queries I tried:
Query 1:
SELECT
title AS 'Etat', ticket_id, user_id,
AVG(TIMESTAMPDIFF(HOUR,
helpdesk_followup.date having title in ('billet ouvert'),
helpdesk_followup.date having title in ('résolu'))
) AS 'moyenne'
FROM helpdesk_followup
GROUP BY user_id;
Query 2:
SELECT
title AS 'Etat', ticket_id, user_id,
AVG(TIMESTAMPDIFF(HOUR,
helpdesk_followup.date as date1,
helpdesk_followup.date as date2)
) AS 'moyenne'
FROM helpdesk_followup
WHERE date1 having title IN 'résolu'
AND date2 having title IN 'billet ouvert'
GROUP BY user_id;
But these queries doesn't get the result I need. How can I add condition to a timestampdiff?

The first column is the starting event and the second column is the end event.
I have done the average in minutes. This SQL works off the title which you may wish to tweak to something more distinct
select a.title, b.title, avg(DateDiff(MINUTE, '00:00:00', b.[date] ) - DateDiff(MINUTE, '00:00:00', a.[date] ) ) from
(select *, row_number() over (order by [date]) hf from helpdesk_followup) a
join (select *, row_number() over (order by [date]) hf from helpdesk_followup) b on (a.hf=b.hf-1)
group by
a.title, b.title
I have left out the user_id from the query as I'm unsure if you wish to break it down using that field.
Hopefully its a start for you to amend into what you need
EDIT: Here is the test data I used for the query
CREATE TABLE [dbo].[helpdesk_followup](
[title] [varchar](50) NULL,
[ticket_id] [int] NULL,
[user_id] [int] NULL,
[date] [datetime] NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
INSERT [dbo].[helpdesk_followup] ([title], [ticket_id], [user_id], [date]) VALUES (N'billet ouvert', 133, NULL, CAST(N'2015-07-22 15:36:00.000' AS DateTime))
GO
INSERT [dbo].[helpdesk_followup] ([title], [ticket_id], [user_id], [date]) VALUES (N'résolu', 133, 19, CAST(N'2015-07-23 15:36:00.000' AS DateTime))
GO
INSERT [dbo].[helpdesk_followup] ([title], [ticket_id], [user_id], [date]) VALUES (N'billet ouvert', 134, 15, CAST(N'2015-07-23 15:36:00.000' AS DateTime))
GO
INSERT [dbo].[helpdesk_followup] ([title], [ticket_id], [user_id], [date]) VALUES (N'résolu', 134, 21, CAST(N'2015-07-27 15:36:00.000' AS DateTime))
GO

Related

Copy Data between SQL Databases

I have 2 Databases (Database1) and (Database2)
DataBase1 has one table (table1)
DataBase2 has one table (table2)
DataBase1.table1 (id as int, code as nvarchar(20), PunhTime as datetime)
DataBase2.table2 (code2 as nvarchar(20), MyDate as datetime, Time1 as nvarchar(8) , Time2 as nvarchar(8))
could Achieve that through SQL ?
thanks in advance
here photo to show how data should copy ..
enter image description here
You may try this
WITH cte_PunchTime AS (
SELECT Code, CONVERT(date, PunchTime) as MyDate, CONVERT(time, PunchTime) as [Time], ROW_NUMBER() OVER (PARTITION BY Code ORDER BY PunchTime) AS [Rank]
FROM DataBase1.table1
)
INSERT INTO DataBase2.table2( Code2, MyDate, Time1, Time2)
SELECT Code, MyDate, MIN([Time]) AS Time1, MAX([Time]) AS Time2
FROM cte_PunchTime
GROUP BY Code, MyDate
You can use the Rank and PIVOT to use it for more than two columns. But number of columns need to be defined. For example, below code is for 4 columns.
WITH cte_Product AS (
SELECT Code, CONVERT(date, PunchTime) as MyDate, CONVERT(time, PunchTime) as [Time]
, ROW_NUMBER() OVER (PARTITION BY Code ORDER BY PunchTime) AS [Rank]
FROM DataBase1.table1
)
INSERT INTO DataBase2.table2( Code, MyDate, Time1, Time2, Time3, Time4)
SELECT * FROM cte_Product
PIVOT (
Min([Time]) FOR [Rank] IN ([1], [2], [3], [4])
) Result;
If they are running the databases on the same server, it is relatively easy to do:
INSERT INTO dbo.DataBase2.table2
(
[code2],
[Time1]
)
SELECT [code], [PunhTime]
FROM dbo.DataBase1.table1
You only have to change the column, since I it is unclear which column should go to which column.

SQL order by needs to check if DATETIME2 is not null then return them first and after order by id

I have two tables and I have trouble figuring out how to do the order by statement to fit my needs.
Basically if the FeaturedUntil column if greater than now then these should be returned first ordered by the PurchasedAt column. Most recent purchases should be first. After these everything should be ordered by the item Id column descending.
Create Table Script
create table Items(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] nvarchar(200) null,
)
create table Feature(
[Id] [int] IDENTITY(1,1) NOT NULL,
[PurchasedAt] [datetime2](7) NOT NULL,
[FeaturedUntil] [datetime2](7) NOT NULL,
[ItemId] [int] NOT NULL,
)
Insert Script
insert into Items(Name) values ('test1')
insert into Feature(PurchasedAt, FeaturedUntil, ItemId) values (dateadd(day, -3, getdate()), dateadd(month, 1, getdate()), ##IDENTITY)
insert into Items(Name) values ('test2')
insert into Feature(PurchasedAt, FeaturedUntil, ItemId) values (dateadd(day, -2, getdate()), dateadd(month, 1, getdate()), ##IDENTITY)
insert into Items(Name) values ('test3')
insert into Feature(PurchasedAt, FeaturedUntil, ItemId) values (dateadd(day, -1, getdate()), dateadd(month, -1, getdate()), ##IDENTITY)
insert into Items(Name) values ('test4')
Select Script
select *
from Items i
left join Feature f on i.Id = f.ItemId
order by
case when f.FeaturedUntil is not null THEN f.PurchasedAt
else i.Id
end
The select should return test2 first as it's FeaturedUntil is greater than now and it is the most recently purchased, second row should be test1 as it is bought before test2. After these should be test4 and last one is test3, because these have no joining Feature table data or the FeatureUntil is not greater than now and these are order by their Item.Id descending.
SELECT *
FROM items i
LEFT JOIN feature f
ON i.id = f.itemid
ORDER BY CASE
WHEN f.featureduntil > getdate THEN purchasedat
ELSE '19000101'
END DESC,
id DESC
You need to order this in descending in order to get the most recent purchase first; the ID sort will still occur, so if you have two PurchasedAt's that are the same, it would sort those 2 by ID.
Based on what you've told us, I think this might be what you're after:
ORDER BY CASE WHEN FeaturedUntil > GETDATE THEN PurchasedAt ELSE '99991231' END ASC, --Future features first, and in date order
--(past have a silly in future date, so always last
Id; --Then ID
Try the following.
select *, case when f.FeaturedUntil is not null THEN f.PurchasedAt else NULL end AS PurchasedAtNew
from Items i
left join Feature f on i.Id = f.ItemId
order by PurchasedAtNew desc, i.Id

Calculate date difference between dates in different rows of a dataset

A table looks like this :
CREATE TABLE [dbo].[HistDT](
[ID] [bigint] NULL,
[StartDtSK] [varchar](8) NULL,
[StartDt] [datetime] NULL,
[status] [nvarchar](30) NULL,
) ON [PRIMARY]
Example data set:
ID | StartDtSK | StartDt | Status |
1 20190520 20-05-2019 12:00:13 10
1 20190520 20-05-2019 10:00:00 5
1 20190414 14-04-2019 13:23:00 2
2 20190312 12-03-2019 10:03:00 10
2 20190308 08-03-2019 18:03:00 1
etc..
I need a query which will display the number of days spent in each status. That would be easy if the table i inherited had an end date. I would then calculate the datediff and pivot for column status values.
Maybe i should create a new table using ssis where i will add an EndDt column which will be the StartDt of the latest added Status.
But is there any way to do this without creating another table?
SQL Server 2008
This is not very pretty, and I haven't tested it for all use cases. I hope you can use it or find inspiration. I'm sure there is a better way :)
declare #table2 table (
[ID] [bigint] NULL,
[StartDtSK] [varchar](8) NULL,
[StartDt] [datetime] NULL,
[status] [nvarchar](30) NULL
)
insert into #table2
values
(1 , '20190520','2019-05-20 12:00:13','10'),
(1 , '20190520','2019-05-20 10:00:00','5'),
(1 , '20190414','2019-04-14 13:23:00','2'),
(2, '20190312', '2019-03-12 10:03:00', '10'),
(2 , '20190308', '2019-03-08 18:03:00', '1')
select *,DATEDIFF(dd,startdt,enddate) as TotalDAys from (
select x.ID,StartDtSK,Startdt,[Status],Enddate from (
select *,ROW_NUMBER() over(partition by id order by startdt) as rn from #table2
) x
cross apply ( select * from (select id,StartDt as Enddate,ROW_NUMBER() over(partition by id order by startdt) as rn2 from #table2 b
)f where (rn +1 = f.rn2 ) and x.id = f.id ) d
union all
select ID,StartDtSK,startdt,[Status],'9999-12-31' as Enddate from (
select *,ROW_NUMBER() over(partition by id order by startdt desc) as rn from #table2
)X where rn=1
)y
order by id,startdt
SQL Server 2008 without cross apply
This might be a bit more pretty :)
select *,DATEDIFF(dd,startdt,enddate) as TotalDAys from (
select x.ID,StartDtSK,Startdt,[Status],case when Enddate is null then '9999-12-31' else Enddate end as Enddate from (
select *,ROW_NUMBER() over(partition by id order by startdt) as rn from #table2
) x
left join (
select * from (select id,StartDt as Enddate,ROW_NUMBER() over(partition by id order by startdt) as rn2 from #table2 b
)f ) d on (rn +1 = d.rn2 ) and x.id = d.id
)y
SQL Server 2012 and above:
Is this what you want?
declare #table2 table (
[ID] [bigint] NULL,
[StartDtSK] [varchar](8) NULL,
[StartDt] [datetime] NULL,
[status] [nvarchar](30) NULL
)
insert into #table2
values
(1 , '20190520','2019-05-20 12:00:13','10'),
(1 , '20190520','2019-05-20 10:00:00','5'),
(1 , '20190414','2019-04-14 13:23:00','2')
select *,Datediff(dd,Startdt,Enddate) as TotalDays from (
select *,LAG(StartDt,1,'9999-12-31') over(partition by ID order by StartDT desc) as EndDate from #table2
)x
Insert a rule that handles current status (9999-12-31) date
Maybe LEAD function is usefull for your question.
Like this
IsNull(DateAdd(SECOND,-1,Cast(LEAD ([StartDt],1) OVER (PARTITION BY [status] ORDER BY [StartDt]) AS DATETIME)),getdate()) AS EndDate

How can I display repeated values only one time and have '-' if it repeats

I have some subqueries that retreives the same values for each PolicyNumber. How can I substitute repeated value with '-' and only display it one in a top row for each policy?
Right now I have this:
But I need something like this:
SELECT
-------------/* GrossPremium*/
(SELECT ISNULL(SUM(tblFin_InvoiceDetails.AmtBilled), 0)
FROM tblFin_InvoiceDetails WITH (NOLOCK)
WHERE (tblFin_InvoiceDetails.ChargeType = 'P')
AND (tblFin_InvoiceDetails.InvoiceNum = INV.InvoiceNum))
AS GrossPremium
--------------/*CompanyCommissionPercentage*/
,((SELECT ISNULL(SUM(tblFin_InvoiceDetails.MGAAmt), 0)
FROM tblFin_InvoiceDetails
WHERE (tblFin_InvoiceDetails.ChargeType = 'P')
AND (tblFin_InvoiceDetails.InvoiceNum = INV.InvoiceNum))
+
CASE WHEN INV.Remitter = 'B' then
(SELECT ISNULL(SUM(tblFin_InvoiceDetails.RemitterAmt), 0)
FROM tblFin_InvoiceDetails
WHERE (tblFin_InvoiceDetails.ChargeType = 'P')
AND (tblFin_InvoiceDetails.InvoiceNum = INV.InvoiceNum))----------------RemitterCommission
ELSE
(SELECT ISNULL(SUM(tblFin_InvoicedItemsPayees.PayeeAmt), 0)
FROM tblFin_InvoicedItemsPayees
INNER JOIN tblFin_PolicyCharges pc on pc.ChargeCode = tblFin_InvoicedItemsPayees.ChargeCode and pc.chargeType = 'P'
WHERE (tblFin_InvoicedItemsPayees.InvoiceNum = INV.InvoiceNum and tblFin_InvoicedItemsPayees.PayeeGuid = INV.ProducerLocationGuid))
END) * 100 /
NULLIF((SELECT ISNULL(SUM(tblFin_InvoiceDetails.AmtBilled), 0)
FROM tblFin_InvoiceDetails WITH (NOLOCK)
WHERE (tblFin_InvoiceDetails.ChargeType = 'P')
AND (tblFin_InvoiceDetails.InvoiceNum = INV.InvoiceNum)),0)
AS CompanyCommissionPercentage
FROM [tblFin_PayablesWorking] PW
INNER JOIN tblFin_Invoices INV ON PW.InvoiceNumber=INV.InvoiceNum
Well since you do not mention you full query and Table schema, i will give your answer with two simple example.If you want replace your repeated value with - the follow this query(please change the columns name according to your needs).
IF YOU WANT TO SELECT YOUR EXISTING TABLE:
;with ts as (
select S1.[ProductID], row_number() over (partition by S1.[ProductID] order by S1.[ProductID]) as seqnum
from (SELECT [SalesID],[ProductID] FROM [Sales]) AS S1 --Replace 'SELECT [ProductID] FROM [Sales]' with your Subquery and change the column accordingly
)
SELECT
(case when seqnum = 1 then [ProductID] ELSE '-' end) as [ProductID]
FROM ts
FOR USING SUBQUERY:
--CREATE TABLE [dbo].[Sales](
-- [SalesID] [uniqueidentifier] NOT NULL DEFAULT (newid()),
-- [ProductID] [int] NOT NULL,
-- [EmployeeID] [int] NOT NULL,
-- [Quantity] [smallint] NOT NULL,
-- [SaleDate] [datetime] NOT NULL CONSTRAINT [DF_SaleDate] DEFAULT (getdate()),
-- CONSTRAINT [PK_SalesID] PRIMARY KEY CLUSTERED
--(
-- [SalesID] ASC
--)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
--) ON [PRIMARY]
--GO
--INSERT [dbo].[Sales] ([SalesID], [ProductID], [EmployeeID], [Quantity], [SaleDate]) VALUES (N'9498d566-e31b-4ac8-ab54-1c898471fba8', 2, 1, 1, CAST(N'2012-03-01 00:00:00.000' AS DateTime))
--INSERT [dbo].[Sales] ([SalesID], [ProductID], [EmployeeID], [Quantity], [SaleDate]) VALUES (N'69c7dff4-fbac-48d3-ae0a-5027c816acd2', 2, 2, 2, CAST(N'2012-04-01 00:00:00.000' AS DateTime))
--INSERT [dbo].[Sales] ([SalesID], [ProductID], [EmployeeID], [Quantity], [SaleDate]) VALUES (N'a40b9505-4a2c-4186-a89b-88a401248a58', 1, 1, 4, CAST(N'2012-02-01 00:00:00.000' AS DateTime))
--INSERT [dbo].[Sales] ([SalesID], [ProductID], [EmployeeID], [Quantity], [SaleDate]) VALUES (N'04856027-d7ad-40fe-889b-8d933595ffde', 3, 1, 2, CAST(N'2012-02-01 00:00:00.000' AS DateTime))
--INSERT [dbo].[Sales] ([SalesID], [ProductID], [EmployeeID], [Quantity], [SaleDate]) VALUES (N'173be2de-3b80-4a3d-8bcc-a74d0d70b3a9', 3, 2, 1, CAST(N'2012-03-01 00:00:00.000' AS DateTime))
--GO
;with ts as (
SELECT
JOIN1.[SalesID] AS [SalesID]
, JOIN1.[ProductID]
, JOIN1.seqnum AS seqnum
, JOIN2.[EmployeeID], JOIN2.seqnum2 AS seqnum2
FROM
(
select row_number() over (order by S1.[SalesID] asc) as RowNumber
, S1.[SalesID] AS [SalesID]
, S1.[ProductID] AS [ProductID]
, row_number() over (partition by S1.[ProductID] order by S1.[SalesID]) as seqnum
from (SELECT [SalesID],[ProductID] FROM [Sales]) AS S1 --Replace 'SELECT [ProductID] FROM [Sales]' with your Subquery ( For Example GrossPremium) and change the column accordingly. Remember you need some thing common for Iner join, in this case [SalesID]
)AS JOIN1
INNER JOIN
(
select row_number() over (order by S2.[SalesID] asc) as RowNumber
, S2.[SalesID] AS [SalesID]
, S2.[EmployeeID] AS [EmployeeID]
, row_number() over (partition by S2.[EmployeeID] order by S2.[SalesID]) as seqnum2
from (SELECT [SalesID],[EmployeeID] FROM [Sales]) AS S2 --Replace 'SELECT [[SalesID]] FROM [Sales]' with your Subquery ( For Example CompanyCommissionPercentage) and change the column accordingly. Remember you need some thing common for Iner join, in this case [SalesID]
)AS JOIN2
ON JOIN1.[SalesID]=JOIN2.[SalesID]
)
SELECT
(case when seqnum = 1 then [ProductID] ELSE '-' end) as [ProductID]
,(case when seqnum2 = 1 then [EmployeeID] ELSE '-' end) as [EmployeeID]
FROM (Select TOP 10000000 *FROM ts ORDER BY [SalesID] ASC ) AS ts -- Mentioning TOP is Must, or it will give Error
I do know why you are using - instead of NULL, - will take space
if you wanted to do it in SQL (you probably shouldn't it's pretty ugly) you could do something like this using LAG(). It relies on having a field that you can use to sort the records for each Policy Number, in my dummy data below I included a field called RecordID to do this.
SELECT
PolicyNumber
,CASE
WHEN LAG(GrossPremium) OVER(PARTITION BY PolicyNumber ORDER BY RecordID) IS NULL
THEN CAST(GrossPremium AS VARCHAR(MAX))
ELSE '-'
END GrossPremium
,CASE
WHEN LAG(CompanyComissionPercentage) OVER(PARTITION BY PolicyNumber ORDER BY RecordID) IS NULL
THEN CAST(CompanyComissionPercentage AS VARCHAR(MAX))
ELSE '-'
END CompanyComissionPercentage
,CASE
WHEN LAG(RemitterCommissionPercentage) OVER(PARTITION BY PolicyNumber ORDER BY RecordID) IS NULL
THEN CAST(RemitterCommissionPercentage AS VARCHAR(MAX))
ELSE '-'
END RemitterCommissionPercentage
,CASE
WHEN LAG(RemitterCommission) OVER(PARTITION BY PolicyNumber ORDER BY RecordID) IS NULL
THEN CAST(RemitterCommission AS VARCHAR(MAX))
ELSE '-'
END GrossCommission
,CASE
WHEN LAG(RemitterCommission) OVER(PARTITION BY PolicyNumber ORDER BY RecordID) IS NULL
THEN CAST(RemitterCommission AS VARCHAR(MAX))
ELSE '-'
END GrossCommission
FROM
(
-- Dummy data
SELECT
1234 PolicyNumber -- Partition the LAG() on the policy number.
,1 RecordID -- use this to order the LAG() function.
,8749.00 GrossPremium
,18 CompanyComissionPercentage
,10 RemitterCommissionPercentage
,874.90 RemitterCommission
,1574.82 GrossCommission
UNION ALL
SELECT
1234
,2 RecordID
,8749.00
,18
,10
,874.90
,1574.82
UNION ALL
SELECT
5678
,1 RecordID
,8749.00
,18
,10
,874.90
,1574.82
) x;

Error with Between clause

I'm getting the following error with this query: Between operator without And in query expression '[DateTime] BETWEEN [StartDate'.
The query and database is in Access 2010
Thank in advance for your help!
SELECT
t1.[Name],
Max(t1.[Sum3Areas]) AS [Max]
FROM (
SELECT
qryUnion.[Name]
, Year(qryUnion.[Date]) as dtYear
, DatePart("ww",[Date]) + IIF(Weekday([Date]) >= 6,1,0) as dtWeek
, SUM(qryUnion.[Amount]) as Sum3Areas
FROM (
SELECT
1 as Source,
EID As [Name],
Closed As [Amount],
DateTime As [Date]
FROM IssueTrakINNER
JOIN [DateRangeCriteria]
ON [DateTime] BETWEEN [StartDate] and [EndDate]
UNION ALL
SELECT
2 as Source,
EID AS [Name],
Completed As [Amount],
DateCompleted AS enter code here[Date]
FROM Kana
INNER JOIN [DateRangeCriteria]
ON [DateTime] BETWEEN [StartDate] and [EndDate]
UNION ALL
SELECT
3 as Source,
EID AS [Name],
Handled As [Amount],
DateTime AS [Date]
FROM Chat
INNER JOIN [DateRangeCriteria]
ON [DateTime] BETWEEN [StartDate] and [EndDate]
)
as qryUnion
GROUP BY qryUnion.[Name] , Year(qryUnion.[Date]), DatePart("ww",[Date]) + IIF(Weekday([Date]) >= 6,1,0)
) AS t1 GROUP BY t1.[Name]
Instead of using the BETWEEN operator in your JOIN...ON statement, use it in the WHERE clause.
For example:
select
...
from tableA
join tableB
on tableA.[DateTime] = tableB.[DateTime]
where tableA.[DateTime] BETWEEN #mm/dd/yyyy# AND #mm/dd/yyyy#