Select 10 Before and 10 After from Identifiers - sql

Do you think the SQL Statement BELOW can be executed in a better way than presented.
Here are the requirements:
The query requires TextIdentifier and a User Name
Identify 10 MP3 files that were created before, and 10 MP3 files that were created after.
If less than 10 MP3 files exist before or after, then pick all available.
The auto-number ID in the table cannot be used, since the DateCreated does not correlate
The code is below the images
Here are some potential scenarios:
QUERY:
DECLARE #UserName NVARCHAR(255)
DECLARE #TextIdentifier NVARCHAR(255)
DECLARE #ProximityDate AS DATETIME
SET #UserName = 'Pete'
SET #TextIdentifier = '456'
SELECT #ProximityDate = [DateCreated]
FROM dbo.ProximitySelectTable
WHERE UserName = #UserName
AND TextIdentifier = #TextIdentifier
SELECT * FROM (
SELECT TOP 10 *
FROM dbo.ProximitySelectTable
WHERE UserName = #UserName
AND [DateCreated] < #ProximityDate
UNION
SELECT *
FROM dbo.ProximitySelectTable
WHERE UserName = #UserName
AND TextIdentifier = #TextIdentifier
UNION
SELECT TOP 10 *
FROM dbo.ProximitySelectTable
WHERE UserName = #UserName
AND [DateCreated] > #ProximityDate
) x
ORDER BY x.DateCreated
Table
CREATE TABLE [dbo].[ProximitySelectTable](
[ID] [int] IDENTITY(1,1) NOT NULL,
[TextIdentifier] [nvarchar](255) NULL,
[UserName] [nvarchar](255) NULL,
[FileName] [nvarchar](255) NULL,
[DateCreated] [datetime] NULL
) ON [PRIMARY]
Test DATA
/****** Object: Table [dbo].[ProximitySelectTable] Script Date: 06/15/2016 15:15:09 ******/
SET IDENTITY_INSERT [dbo].[ProximitySelectTable] ON
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (1, N'2has721', N'Pete', N'c:\123456.mp3', CAST(0x0000A13900000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (2, N'123', N'Pete', N'c:\223456.mp3', CAST(0x0000A58000000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (3, N'456', N'Pete', N'c:\323456.mp3', CAST(0x0000A5DB00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (4, N'789', N'Pete', N'c:\423456.mp3', CAST(0x0000A58000000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (5, N'1011', N'Pete', N'c:\523456.mp3', CAST(0x0000A5F900000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (6, N'1112', N'Jack', N'c:\623456.mp3', CAST(0x0000A5BC00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (7, N'1312', N'Jack', N'c:\723456.mp3', CAST(0x0000A56C00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (8, N'1412', N'Jack', N'c:\823456.mp3', CAST(0x0000A54300000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (9, N'1516', N'Jack', N'c:\923456.mp3', CAST(0x0000A58000000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (10, N'1817', N'Jack', N'c:\133456.mp3', CAST(0x0000A5F900000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (11, N'1819', N'Sherry', N'c:\143456.mp3', CAST(0x0000A52400000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (12, N'2021', N'Sherry', N'c:\153456.mp3', CAST(0x0000A5BC00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (13, N'2122', N'Sherry', N'c:\163456.mp3', CAST(0x0000A5DB00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (14, N'2123', N'Pete', N'c:\173456.mp3', CAST(0x0000A52400000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (15, N'2124', N'Pete', N'c:\183456.mp3', CAST(0x0000A13900000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (16, N'2125', N'Sherry', N'c:\193456.mp3', CAST(0x0000A50600000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (17, N'2126', N'Jack', N'c:\124456.mp3', CAST(0x0000A5BC00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (18, N'2127', N'Pete', N'c:\125456.mp3', CAST(0x0000A13900000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (19, N'2128', N'Sherry', N'c:\aaaa1.mp3', CAST(0x0000A4E700000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (20, N'2129', N'Jack', N'c:\aaaa2.mp3', CAST(0x0000A5F900000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (21, N'3121', N'Jack', N'c:\aaaa3.mp3', CAST(0x0000A13900000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (22, N'3122', N'Sherry', N'c:\aaaa4.mp3', CAST(0x0000A54300000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (23, N'3123', N'Jack', N'c:\aaaa5.mp3', CAST(0x0000A5BC00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (24, N'3124', N'Jack', N'c:\aaaa6.mp3', CAST(0x0000A13900000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (25, N'3125', N'Sherry', N'c:\aaaa7.mp3', CAST(0x0000A5DB00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (26, N'3126', N'Jack', N'c:\aaaa8.mp3', CAST(0x0000A56C00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (27, N'3127', N'Pete', N'c:\aaaa9.mp3', CAST(0x0000A5F900000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (28, N'3128', N'Pete', N'c:\bbbbb1.mp3', CAST(0x0000A54300000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (29, N'3129', N'Sherry', N'c:\bbbbb2.mp3', CAST(0x0000A5BC00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (30, N'4121', N'Jack', N'c:\bbbbb3.mp3', CAST(0x0000A52400000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (31, N'4122', N'Pete', N'c:\bbbbb4.mp3', CAST(0x0000A5F900000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (32, N'4123', N'Jack', N'c:\bbbbb5.mp3', CAST(0x0000A5DB00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (33, N'4124', N'Jack', N'c:\bbbbb6.mp3', CAST(0x0000A50600000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (34, N'4125', N'Sherry', N'c:\bbbbb7.mp3', CAST(0x0000A5BC00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (35, N'4126', N'Jack', N'c:\bbbbb8.mp3', CAST(0x0000A56C00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (36, N'4127', N'Jack', N'c:\bbbbb9.mp3', CAST(0x0000A4E700000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (37, N'4128', N'Jack', N'c:\cccccc1.mp3', CAST(0x0000A54300000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (38, N'4129', N'Pete', N'c:\cccccc2.mp3', CAST(0x0000A5DB00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (39, N'5121', N'Sherry', N'c:\cccccc3.mp3', CAST(0x0000A5BC00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (40, N'5122', N'Jack', N'c:\cccccc4.mp3', CAST(0x0000A56C00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (41, N'5123', N'Jack', N'c:\cccccc5.mp3', CAST(0x0000A54300000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (42, N'5124', N'Sherry', N'c:\cccccc6.mp3', CAST(0x0000A5DB00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (43, N'5125', N'Pete', N'c:\cccccc7.mp3', CAST(0x0000A5BC00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (44, N'5126', N'Jack', N'c:\cccccc8.mp3', CAST(0x0000A5DB00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (45, N'5127', N'Pete', N'c:\cccccc9.mp3', CAST(0x0000A4E700000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (46, N'5128', N'Pete', N'c:\ddddd1.mp3', CAST(0x0000A54300000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (47, N'5129', N'Pete', N'c:\ddddd2.mp3', CAST(0x0000A4E700000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (48, N'6121', N'Pete', N'c:\ddddd3.mp3', CAST(0x0000A5F900000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (49, N'6122', N'Pete', N'c:\ddddd4.mp3', CAST(0x0000A50600000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (50, N'6123', N'Pete', N'c:\ddddd5.mp3', CAST(0x0000A5BC00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (51, N'6124', N'Pete', N'c:\ddddd6.mp3', CAST(0x0000A52400000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (52, N'6125', N'Pete', N'c:\ddddd7.mp3', CAST(0x0000A5F900000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (53, N'6126', N'Pete', N'c:\ddddd8.mp3', CAST(0x0000A50600000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (54, N'6127', N'Pete', N'c:\ddddd9.mp3', CAST(0x0000A5DB00000000 AS DateTime))
INSERT [dbo].[ProximitySelectTable] ([ID], [TextIdentifier], [UserName], [FileName], [DateCreated]) VALUES (55, N'6128', N'Jack', N'c:\ddddd0.mp3', CAST(0x0000A5F900000000 AS DateTime))
SET IDENTITY_INSERT [dbo].[ProximitySelectTable] OFF

Your current query is not correct (missing ORDER BY and unneeded UNION rather than UNION ALL) but a fixed version of it could be the most efficient with the right indexes.
My row_number answer first is
WITH CTE1
AS (SELECT *,
ROW_NUMBER() OVER (ORDER BY DateCreated) AS RN
FROM [ProximitySelectTable]
WHERE UserName = #UserName),
CTE2
AS (SELECT *,
MAX(CASE
WHEN #TextIdentifier = TextIdentifier
THEN RN
END) OVER () AS FocusRN
FROM CTE1)
SELECT ID,
TextIdentifier,
UserName,
FileName,
DateCreated
FROM CTE2
WHERE RN BETWEEN FocusRN - 10 AND FocusRN + 10
ORDER BY DateCreated
And a fixed version of your current query
SELECT * FROM (
SELECT TOP 10 *
FROM dbo.ProximitySelectTable
WHERE UserName = #UserName
AND [DateCreated] < #ProximityDate
ORDER BY [DateCreated] DESC
UNION ALL
SELECT *
FROM dbo.ProximitySelectTable
WHERE UserName = #UserName
AND TextIdentifier = #TextIdentifier
UNION ALL
SELECT TOP 10 *
FROM dbo.ProximitySelectTable
WHERE UserName = #UserName
AND [DateCreated] > #ProximityDate
ORDER BY [DateCreated] ASC
) x
ORDER BY x.DateCreated
This would need an index on UserName, TextIdentifier for the initial seek and on UserName, DateCreated to get the TOP 10s with a seek and no sort.

Don't have a box running SQL Server 2008 handy but I checked that all functions below are available in 2008:
DECLARE #UserName NVARCHAR(255) = 'Pete'
DECLARE #TextIdentifier NVARCHAR(255) = '456'
;WITH
cte1 AS
(
SELECT *,
ROW_NUMBER() OVER (ORDER BY DateCreated) AS RowNumber
FROM ProximitySelectTable
),
cte2 AS
(
SELECT TOP 1
RowNumber
FROM cte1
WHERE UserName = #UserName AND TextIdentifier = #TextIdentifier
ORDER BY RowNumber
)
SELECT *
FROM cte1, cte2
WHERE cte1.RowNumber BETWEEN (cte2.RowNumber - 10) AND (cte2.RowNumber + 10)
cte1 numbers all rows from 1 to n. cte2 find the row number for the target row. The final SELECT simply scan for the past 10 and next 10 rows.

Here is pseudo-code for a ROW_NUMBER solution:
WITH cte1 AS (
SELECT desiredcolumns, ROW_NUMBER() OVER (ORDER BY DateCol) AS rn
FROM MyTable
),
cte2 AS (
SELECT ID, rn
FROM cte1
WHERE TextIdentifier = #TextIdentifier
)
SELECT desiredcolumns
FROM cte1
CROSS JOIN cte2
WHERE cte1.rn > cte2.rn - 10
AND cte1.rn < cte2.rn + 9

Related

SSMS - Seeking help writing a select statement to return duplicates in SQL [Example included]

I am trying to implement validation to check whether the same FX rate has been entered in reverse order for the same date. Users would populate a spreadsheet consisting of five columns:
Date
From Currency
To Currency
Rate
Multiply/Divide
The user would add data into a spreadsheet to import through the system, below is a mock example of how the data would look in the table in the database:
I have the structure of the validation in place, I am just wondering how I would write a select statement in order to return all rows which:
Have both directions for the same date, as shown in the first two rows in the image above^. USD & GBP both have Multiply (M) and Divide (D) for the 01/02/2023, therefore I would like to return these rows as to fail the validation, none of the other rows in the example should be returned as they are valid.
I thought I'd include a script to create the table shown in the image above which includes the exact data shown. I am hoping to return the first two rows from the table above
CREATE TABLE [tblFXRates](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Date] [datetime] NOT NULL,
[FromCurrency] [nvarchar](3) NOT NULL,
[ToCurrency] [nvarchar](3) NOT NULL,
[Rate] [decimal](19, 2) NOT NULL,
[Divide/Multiply] [nvarchar](1) NOT NULL
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [tblFXRates] ON
GO
INSERT [tblFXRates] ([ID], [Date], [FromCurrency], [ToCurrency], [Rate], [Divide/Multiply]) VALUES (1, CAST(N'2023-02-01T00:00:00.000' AS DateTime), N'USD', N'GBP', CAST(1.30 AS Decimal(19, 2)), N'M')
GO
INSERT [tblFXRates] ([ID], [Date], [FromCurrency], [ToCurrency], [Rate], [Divide/Multiply]) VALUES (2, CAST(N'2023-02-01T00:00:00.000' AS DateTime), N'GBP', N'USD', CAST(1.30 AS Decimal(19, 2)), N'D')
GO
INSERT [tblFXRates] ([ID], [Date], [FromCurrency], [ToCurrency], [Rate], [Divide/Multiply]) VALUES (3, CAST(N'2023-02-01T00:00:00.000' AS DateTime), N'GBP', N'EUR', CAST(1.11 AS Decimal(19, 2)), N'M')
GO
INSERT [tblFXRates] ([ID], [Date], [FromCurrency], [ToCurrency], [Rate], [Divide/Multiply]) VALUES (4, CAST(N'2023-02-01T00:00:00.000' AS DateTime), N'GBP', N'GBP', CAST(1.00 AS Decimal(19, 2)), N'M')
GO
INSERT [tblFXRates] ([ID], [Date], [FromCurrency], [ToCurrency], [Rate], [Divide/Multiply]) VALUES (5, CAST(N'2023-02-01T00:00:00.000' AS DateTime), N'GBP', N'GBP', CAST(1.00 AS Decimal(19, 2)), N'D')
GO
INSERT [tblFXRates] ([ID], [Date], [FromCurrency], [ToCurrency], [Rate], [Divide/Multiply]) VALUES (6, CAST(N'2023-02-01T00:00:00.000' AS DateTime), N'USD', N'USD', CAST(1.00 AS Decimal(19, 2)), N'M')
GO
INSERT [tblFXRates] ([ID], [Date], [FromCurrency], [ToCurrency], [Rate], [Divide/Multiply]) VALUES (7, CAST(N'2023-02-01T00:00:00.000' AS DateTime), N'USD', N'USD', CAST(1.00 AS Decimal(19, 2)), N'D')
GO
INSERT [tblFXRates] ([ID], [Date], [FromCurrency], [ToCurrency], [Rate], [Divide/Multiply]) VALUES (8, CAST(N'2023-02-01T00:00:00.000' AS DateTime), N'EUR', N'GBP', CAST(0.90 AS Decimal(19, 2)), N'M')
GO
SET IDENTITY_INSERT [tblFXRates] OFF
GO
Edit:
this will do:
assumig we want only those with different FromCurrency & ToCurrency, but of course you can change this.
SELECT
tbl1.*
FROM
test.tblfxrates tbl1
inner join
test.tblfxrates tbl2 on tbl2.FromCurrency = tbl1.ToCurrency and tbl2.ToCurrency = tbl1.FromCurrency and tbl1.FromCurrency <> tbl1.ToCurrency and tbl1.Date = tbl2.Date
where
tbl1.DivideMultiply <> tbl2.DivideMultiply
order by
tbl1.ID
it will return the first 2 lines

Count of A Column For Last 12 Months and Individual Month

I've a bit complex requirement and for the understanding, let me make it clear with easy example. Suppose, we have to calculate the quantity of products purchased by consumers month-wise for the last 12 months. So what we do is the following:
SELECT DATENAME(MONTH, m.InvoiceDate) Month,
COUNT(m.Quantity) Quantity FROM CustomerInvoice m WHERE
DATEDIFF(month, m.InvoiceDate, GETDATE()) <= 12 AND YEAR(m.InvoiceDate) = '2018'
GROUP BY DATENAME(MONTH, m.InvoiceDate)
ORDER BY DATENAME(MONTH, m.InvoiceDate) DESC;
Output - So this is what we get:
Month Quantity
January 1
February 1
March 1
April 2
May 1
June 3
July 1
August 2
In my case, it's bit complicated as the following sample:
So if the input is July 2018, it should calculate the last 12 months quantity or value as well individual month's last 12 months value too. This seems to be something like recursive call. But pretty unsure how to accomplish this in the right way - Any ideas or samples would be highly appreciated - Thanks.
Sample Table With Data:
CREATE TABLE [dbo].[CustomerInvoice](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ProductID] [int] NULL,
[Quantity] [float] NULL,
[Details] [varchar](max) NULL,
[InvoiceID] [varchar](40) NULL,
[CustomerID] [int] NULL,
[InvoiceDate] [datetime] NULL
)
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (1, 2, 2, N'Awesome Collections', N'20151129115910', 1, CAST(0x0000A94200000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (2, 1, 2, N'Joss Collections', N'20151129115910', 1, CAST(0x0000A94200000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (3, 2, 2, N'Awesome Collections', N'20151129115910', 1, CAST(0x0000A91900000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (4, 1, 2, N'Awesome Collections', N'20151129115910', 1, CAST(0x0000A8FC00000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (5, 2, 2, N'Awesome Collections', N'20151129115912', 2, CAST(0x0000A8F300000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (6, 1, 2, N'Joss Collections', N'20151129115912', 2, CAST(0x0000A8F400000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (7, 1, 4, N'Joss Collections', N'20151130120336', 1, CAST(0x0000A8DF00000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (8, 1, 10, N'Awesome Collections', N'20151130120336', 1, CAST(0x0000A8BA00000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (9, 2, 10, N'Awesome Collections', N'20151130120616', 1, CAST(0x0000A8BE00000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (10, 1, 10, N'Joss Collections', N'20151130120616', 1, CAST(0x0000A8AB00000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (11, 2, 12, N'Great', N'20151130125238', 2, CAST(0x0000A88700000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (12, 1, 12, N'Great', N'20151130125238', 2, CAST(0x0000A86F00000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (13, 2, 4, N'Great', N'20151202085309', 6, CAST(0x0000A85700000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (14, 1, 10, N'Joss Collections', N'20151202085309', 6, CAST(0x0000A81E00000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (15, 2, 10, N'Customer likes this a lot.', N'20151203101624', 1, CAST(0x0000A80F00000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (16, 2, 10, N'Customer likes this a lot.', N'20151203102205', 1, CAST(0x0000A7E500000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (17, 2, 2, N'Wao!! Great.', N'20151203103844', 1, CAST(0x0000A7CE00000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (18, 1, 4, N'Just Awesome.', N'20151203103844', 1, CAST(0x0000A7BD00000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (19, 2, 12, N'Customers just love the product.', N'20151203104143', 2, CAST(0x0000A78600000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (20, 1, 2, N'Awesome Collections.', N'20151203104143', 2, CAST(0x0000A79000000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (21, 2, 6, N'Awesome Collections.', N'20151203104945', 1, CAST(0x0000A78F00000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (22, 1, 6, N'Great Collection.', N'20151203104945', 1, CAST(0x0000A79300000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (23, 1, 10, N'Customer likes this a lot.', N'20151203105528', 1, CAST(0x0000A76F00000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (24, 2, 4, N'Great Collection.', N'20151203105528', 1, CAST(0x0000A75300000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (25, 2, 1, N'Just Great.', N'20151203110653', 7, CAST(0x0000A75C00000000 AS DateTime))
INSERT [dbo].[CustomerInvoice] ([ID], [ProductID], [Quantity], [Details], [InvoiceID], [CustomerID], [InvoiceDate]) VALUES (26, 1, 1, N'Customers are happy with the product.', N'20151203110653', 7, CAST(0x0000A76400000000 AS DateTime))
Update 1 - This calculation is done for last 12 months and please see how the quantity is calculated below:
Month-Year Quantity
Jul 2018 80 (Sum of quantity from Jul 2018 to Jun 2017)
Jun 2018 70 (Sum of quantity from Jun 2018 to May 2017)
May 2018 42 (Sum of quantity from May 2018 to Apr 2017)
Apr 2018 11 ...........................................
Mar 2018 6 ...........................................
Feb 2018 10 ...........................................
Jan 2018 16 ...........................................
Dec 2017 1 ...........................................
..........................................................
Jun 2017 10 (Sum of quantity from Jun 2017 to May 2016)
This answers the question for SQL Server 2012+ (the SQL Server version was not specified when I answered the question).
I would recommend using cumulative sums. This assumes that you have data for each month, but that seems reasonable. For a cumulative year-to-date:
SELECT YEAR(m.InvoiceDate) as yyyy,
MONTH(m.InvoiceDate) as mm,
SUM(m.Quantity) as Quantity,
SUM(SUM(m.Quantity)) OVER (PARTITION BY YEAR(m.InvoiceDate)
ORDER BY MONTH(m.InvoiceDate)
)
FROM CustomerInvoice m
WHERE YEAR(m.InvoiceDate) = 2018
GROUP BY YEAR(m.InvoiceDate), MONTH(m.InvoiceDate)
ORDER BY YEAR(m.InvoiceDate), MONTH(m.InvoiceDate);
Note that this uses SUM(m.Quantity) rather than COUNT(). SUM() makes more sense based on your description.
If you want a cumulative running 12-month sum, ignoring year boundaries, use a windowing clause:
SELECT YEAR(m.InvoiceDate) as yyyy,
MONTH(m.InvoiceDate) as mm,
SUM(m.Quantity) as Quantity,
SUM(SUM(m.Quantity)) OVER (PARTITION BY YEAR(m.InvoiceDate)
ORDER BY MONTH(m.InvoiceDate)
ROWS BETWEEN 11 PRECEDING AND CURRENT ROW
)
FROM CustomerInvoice m
GROUP BY YEAR(m.InvoiceDate), MONTH(m.InvoiceDate)
ORDER BY YEAR(m.InvoiceDate), MONTH(m.InvoiceDate);
EDIT:
In SQL Server 2008, you can express the first query as:
WITH ym as (
SELECT YEAR(m.InvoiceDate) as yyyy,
MONTH(m.InvoiceDate) as mm,
SUM(m.Quantity) as Quantity,
FROM CustomerInvoice m
WHERE YEAR(m.InvoiceDate) = 2018
GROUP BY YEAR(m.InvoiceDate), MONTH(m.InvoiceDate)
)
SELECT ym.yyyymm, ym.quantity, ym2.sum_Quantity)
FROM ym CROSS APPLY
(SELECT SUM(ym2.quantity) as sum_quantity
FROM ym ym2
WHERE ym.yyyy = ym2.yyyy AND ym2.month <= ym.month
) ym2
ORDER BY YEAR(m.InvoiceDate), MONTH(m.InvoiceDate);
For a rolling sum in SQL Server 2008:
WITH ym as (
SELECT YEAR(m.InvoiceDate) as yyyy,
MONTH(m.InvoiceDate) as mm,
SUM(m.Quantity) as Quantity,
FROM CustomerInvoice m
WHERE YEAR(m.InvoiceDate) = 2018
GROUP BY YEAR(m.InvoiceDate), MONTH(m.InvoiceDate)
)
SELECT ym.yyyymm, ym.quantity, ym2.sum_Quantity)
FROM ym CROSS APPLY
(SELECT SUM(ym2.quantity) as sum_quantity
FROM ym ym2
WHERE ym2.InvoiceDate >= DATEADD(year, -1, ym.InvoiceDate) AND
ym2.InvoiceDate <= ym.InvoiceDate
) ym2
ORDER BY YEAR(m.InvoiceDate), MONTH(m.InvoiceDate);
Try this:
WITH t (month_name,month_id,quantity)
AS
(
select month_name,month_id,quantity
from CustomerInvoice
cross apply (select datediff(month,0,InvoiceDate) month_id,format(InvoiceDate,'MMMM yyyy') month_name)stats
)
SELECT months_tbl.*,sum(quantity) from
(select distinct month_name,month_id from t)months_tbl
inner join t on t.month_id between months_tbl.month_id-11 and months_tbl.month_id
group by months_tbl.month_name,months_tbl.month_id
order by month_id asc

SQL Server : complex query to get average time

I have a complex SQL query please resolve. Here is the details of it.
As I think the screenshot I have attached shows all the requirements. The system works like this.
I am creating a text file in my application and logging the same in SQL Server also. As soon as this file gets created, with same name another file gets created with .html extension. I am logging the html file also in SQL Server. So basically if you want you can group the rows on the basis of file name to get a single request.
Now by using SQL I want to get the time difference between these two files. As you can see in the image that first request has taken 547 milliseconnds.
The same way I want to get the average time taken by all the requests in a minute or hour.
SQL Script
CREATE TABLE [dbo].[DebugInfo](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[FileName] [varchar](250) NULL,
[Message] [varchar](250) NULL,
[Time] [datetime] NULL,
[UserId] [int] NULL,
CONSTRAINT [PK_DebugInfo] PRIMARY KEY CLUSTERED
(
[Id] 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
SET ANSI_PADDING OFF
GO
SET IDENTITY_INSERT [dbo].[DebugInfo] ON
INSERT [dbo].[DebugInfo] ([Id], [FileName], [Message], [Time], [UserId]) VALUES (1, N'\\172.16.1.18\datadrive\vol2\SCANNING\SCAN\NovToWin\SIP1\WH000001.txt', N'File Is LOCKED Count:- 511', CAST(0x0000A43300CF83FD AS DateTime), NULL)
INSERT [dbo].[DebugInfo] ([Id], [FileName], [Message], [Time], [UserId]) VALUES (2, N'\\172.16.1.18\datadrive\vol2\SCANNING\SCAN\NovToWin\SIP1\WH000001.htm', N'File Is LOCKED Count:- 335', CAST(0x0000A43300CF84A1 AS DateTime), NULL)
INSERT [dbo].[DebugInfo] ([Id], [FileName], [Message], [Time], [UserId]) VALUES (3, N'\\172.16.1.18\datadrive\vol2\SCANNING\SCAN\NovToWin\SIP1\WH000002.txt', N'File Is LOCKED Count:- 672', CAST(0x0000A43300D0072D AS DateTime), NULL)
INSERT [dbo].[DebugInfo] ([Id], [FileName], [Message], [Time], [UserId]) VALUES (4, N'\\172.16.1.18\datadrive\vol2\SCANNING\SCAN\NovToWin\SIP1\WH000002.htm', N'File Is LOCKED Count:- 1006', CAST(0x0000A43300D00895 AS DateTime), NULL)
INSERT [dbo].[DebugInfo] ([Id], [FileName], [Message], [Time], [UserId]) VALUES (5, N'\\172.16.1.18\datadrive\vol2\SCANNING\SCAN\NovToWin\SIP1\WH000003.txt', N'File Is LOCKED Count:- 254', CAST(0x0000A43300D00FC9 AS DateTime), NULL)
INSERT [dbo].[DebugInfo] ([Id], [FileName], [Message], [Time], [UserId]) VALUES (6, N'\\172.16.1.18\datadrive\vol2\SCANNING\SCAN\NovToWin\SIP1\WH000003.htm', N'File Is LOCKED Count:- 136', CAST(0x0000A43300D01001 AS DateTime), NULL)
INSERT [dbo].[DebugInfo] ([Id], [FileName], [Message], [Time], [UserId]) VALUES (7, N'\\172.16.1.18\datadrive\vol2\SCANNING\SCAN\NovToWin\SIP1\WH000004.txt', N'File Is LOCKED Count:- 772', CAST(0x0000A43300D0167E AS DateTime), NULL)
INSERT [dbo].[DebugInfo] ([Id], [FileName], [Message], [Time], [UserId]) VALUES (8, N'\\172.16.1.18\datadrive\vol2\SCANNING\SCAN\NovToWin\SIP1\WH000004.htm', N'File Is LOCKED Count:- 181', CAST(0x0000A43300D016C5 AS DateTime), NULL)
INSERT [dbo].[DebugInfo] ([Id], [FileName], [Message], [Time], [UserId]) VALUES (9, N'\\172.16.1.18\datadrive\vol2\SCANNING\SCAN\NovToWin\SIP1\WH000005.txt', N'File Is LOCKED Count:- 347', CAST(0x0000A43300D01B65 AS DateTime), NULL)
INSERT [dbo].[DebugInfo] ([Id], [FileName], [Message], [Time], [UserId]) VALUES (10, N'\\172.16.1.18\datadrive\vol2\SCANNING\SCAN\NovToWin\SIP1\WH000005.htm', N'File Is LOCKED Count:- 117', CAST(0x0000A43300D01B8F AS DateTime), NULL)
INSERT [dbo].[DebugInfo] ([Id], [FileName], [Message], [Time], [UserId]) VALUES (11, N'\\172.16.1.18\datadrive\vol2\SCANNING\SCAN\NovToWin\SIP1\WH000006.txt', N'File Is LOCKED Count:- 572', CAST(0x0000A43300F13506 AS DateTime), NULL)
INSERT [dbo].[DebugInfo] ([Id], [FileName], [Message], [Time], [UserId]) VALUES (12, N'\\172.16.1.18\datadrive\vol2\SCANNING\SCAN\NovToWin\SIP1\WH000006.htm', N'File Is LOCKED Count:- 562', CAST(0x0000A43300F13632 AS DateTime), NULL)
Here is what i have used to generate the RawFileName
SELECT *, SUBSTRING((REVERSE
(
SUBSTRING
(
REVERSE(FileName),0,CHARINDEX('\',REVERSE(FileName))
)
)),0, CHARINDEX('.',REVERSE
(
SUBSTRING
(
REVERSE(FileName),0,CHARINDEX('\',REVERSE(FileName))
)
))) AS RawFileName from DebugInfo
Thanks
Does this do what you want?
select avg(diff_ms * 1.0)
from (select datediff(millisecond, min(time), max(time)) as diff_ms
from t
group by rawfilename
) t;
select avg(diff)
from ( select filename, DATEDIFF(MILLISECOND, Time, nextTime) as diff
from ( select [FileName]
, [Time]
, lead(Time, 1, 0) OVER (ORDER BY id) AS nextTime
, row_number() over (partition by FileName order by Time) as rn
from [DebugInfo]
) tt
where tt.rn = 1
) ttt
select avg(diff)
from ( select datediff(millisecond, minTime, maxTime) as diff
from ( select min(time) as minTime, max(time) ss maxTime
from [DebugInfo]
group by rawfilename
) tt
) ttt;

Grouping with partition and over in TSql

I have a simple table
CREATE TABLE [dbo].[Tooling](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
[Status] [int] NOT NULL,
[DateFinished] [datetime] NULL,
[Tooling] [nvarchar](50) NULL,
[Updated] [datetime] NULL,
) ON [PRIMARY]
with following values
SET IDENTITY_INSERT [dbo].[Tooling] ON
GO
INSERT [dbo].[Tooling] ([Id], [Name], [Status], [DateFinished], [Tooling], [Updated]) VALUES (1, N'Large', 0, NULL, NULL, CAST(N'2015-05-05 00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Tooling] ([Id], [Name], [Status], [DateFinished], [Tooling], [Updated]) VALUES (2, N'Large', 1, NULL, N'1', CAST(N'2015-05-10 00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Tooling] ([Id], [Name], [Status], [DateFinished], [Tooling], [Updated]) VALUES (3, N'Small', 0, NULL, N'2', CAST(N'2015-05-11 00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Tooling] ([Id], [Name], [Status], [DateFinished], [Tooling], [Updated]) VALUES (4, N'Large', 2, NULL, N'1', CAST(N'2015-05-12 00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Tooling] ([Id], [Name], [Status], [DateFinished], [Tooling], [Updated]) VALUES (5, N'Large', 2, NULL, N'2', CAST(N'2015-05-12 00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Tooling] ([Id], [Name], [Status], [DateFinished], [Tooling], [Updated]) VALUES (6, N'Large', 1, NULL, N'1', CAST(N'2015-05-13 00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Tooling] ([Id], [Name], [Status], [DateFinished], [Tooling], [Updated]) VALUES (7, N'Large', 1, NULL, N'2', CAST(N'2015-05-14 00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Tooling] ([Id], [Name], [Status], [DateFinished], [Tooling], [Updated]) VALUES (8, N'Small', 1, CAST(N'2015-05-15 00:00:00.000' AS DateTime), N'2', CAST(N'2015-05-15 00:00:00.000' AS DateTime))
GO
SET IDENTITY_INSERT [dbo].[Tooling] OFF
I want to create a view of the table that looks like its an entirely own table.
SELECT Id, Name, Status, DateFinished
FROM Tooling t order by t.id
If i run that I would like that the records with id 5 and 7 should be excluded since they dont change in the selected set from the previous row.
I had an idea to solve this by using, ROW_NUMBER() over partition
And by using group by but thats seems to incorrect(Could not to get it to work at all)
How do I group it when the should be grouped on that the value change and not the value it contains?
Any suggestions to solve this?
My end goal is also try to convert this to linq to entities...
OK, supposing it's ordered by id
select *
from (
select *, rng = row_number() over (partition by grp order by id)
from (
select *, grp = row_number() over (order by id) - row_number() over (partition by Name, Status, DateFinished order by id)
from tooling ) g
) gn
where rng = 1
order by id

SQL Server select best available time

Below is my time slots table which indicates the reserved time from isReserved column - 0 is not reserved. I have all the day minutes available in this table.
I need to select best available time based from the table.
Example:
If I need to book a 4 minutes job, then it should return the first available time, and when I need to book a 30 minutes job, then the query should not return the first available as there are not enough minutes available in that timeslot and return the next first available.
I am using sql server 2008 r2
With the following query
Select timeslot from jpcbtimeslots where timeslot > #starttime and timeslot<= #endtime and isreserved ='0'
CREATE TABLE [dbo].[JPCBTimeSlots](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[BayID] [int] NULL,
[TimeSlot] [datetime] NULL,
[IsReserved] [int] NULL,
CONSTRAINT [PK_JPCBTimeSlots] PRIMARY KEY CLUSTERED ( [ID] 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
SET IDENTITY_INSERT [dbo].[JPCBTimeSlots] ON
INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (1, 1, CAST(0x0000A62200AC3392 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (2, 1, CAST(0x0000A62200AC79E2 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (3, 1, CAST(0x0000A62200ACC032 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (4, 1, CAST(0x0000A62200AD0682 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (5, 1, CAST(0x0000A62200AD4CD2 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (6, 1, CAST(0x0000A62200AD9322 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (7, 1, CAST(0x0000A62200ADD972 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (8, 1, CAST(0x0000A62200AE1FC2 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (9, 1, CAST(0x0000A62200AE6612 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (10, 1, CAST(0x0000A62200AEAC62 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (11, 1, CAST(0x0000A62200AEF2B2 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (12, 1, CAST(0x0000A62200AF3902 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (13, 1, CAST(0x0000A62200AF7F52 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (14, 1, CAST(0x0000A62200AFC5A2 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (15, 1, CAST(0x0000A62200B00BF2 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (16, 1, CAST(0x0000A62200B05242 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (17, 1, CAST(0x0000A62200B09892 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (18, 1, CAST(0x0000A62200B0DEE2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (19, 1, CAST(0x0000A62200B12532 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (20, 1, CAST(0x0000A62200B16B82 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (21, 1, CAST(0x0000A62200B1B1D2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (22, 1, CAST(0x0000A62200B1F822 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (23, 1, CAST(0x0000A62200B23E72 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (24, 1, CAST(0x0000A62200B284C2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (25, 1, CAST(0x0000A62200B2CB12 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (26, 1, CAST(0x0000A62200B31162 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (27, 1, CAST(0x0000A62200B357B2 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (28, 1, CAST(0x0000A62200B39E02 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (29, 1, CAST(0x0000A62200B3E452 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (30, 1, CAST(0x0000A62200B42AA2 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (31, 1, CAST(0x0000A62200B470F2 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (32, 1, CAST(0x0000A62200B4B742 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (33, 1, CAST(0x0000A62200B4FD92 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (34, 1, CAST(0x0000A62200B543E2 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (35, 1, CAST(0x0000A62200B58A32 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (36, 1, CAST(0x0000A62200B5D082 AS DateTime), 1) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (37, 1, CAST(0x0000A62200B616D2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (38, 1, CAST(0x0000A62200B65D22 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (39, 1, CAST(0x0000A62200B6A372 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (40, 1, CAST(0x0000A62200B6E9C2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (41, 1, CAST(0x0000A62200B73012 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (42, 1, CAST(0x0000A62200B77662 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (43, 1, CAST(0x0000A62200B7BCB2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (44, 1, CAST(0x0000A62200B80302 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (45, 1, CAST(0x0000A62200B84952 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (46, 1, CAST(0x0000A62200B88FA2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (47, 1, CAST(0x0000A62200B8D5F2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (48, 1, CAST(0x0000A62200B91C42 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (49, 1, CAST(0x0000A62200B96292 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (50, 1, CAST(0x0000A62200B9A8E2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (51, 1, CAST(0x0000A62200B9EF32 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (52, 1, CAST(0x0000A62200BA3582 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (53, 1, CAST(0x0000A62200BA7BD2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (54, 1, CAST(0x0000A62200BAC222 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (55, 1, CAST(0x0000A62200BB0872 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (56, 1, CAST(0x0000A62200BB4EC2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (57, 1, CAST(0x0000A62200BB9512 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (58, 1, CAST(0x0000A62200BBDB62 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (59, 1, CAST(0x0000A62200BC21B2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (60, 1, CAST(0x0000A62200BC6802 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (61, 1, CAST(0x0000A62200BCAE52 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (62, 1, CAST(0x0000A62200BCF4A2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (63, 1, CAST(0x0000A62200BD3AF2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (64, 1, CAST(0x0000A62200BD8142 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (65, 1, CAST(0x0000A62200BDC792 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (66, 1, CAST(0x0000A62200BE0DE2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (67, 1, CAST(0x0000A62200BE5432 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (68, 1, CAST(0x0000A62200BE9A82 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (69, 1, CAST(0x0000A62200BEE0D2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (70, 1, CAST(0x0000A62200BF2722 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (71, 1, CAST(0x0000A62200BF6D72 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (72, 1, CAST(0x0000A62200BFB3C2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (73, 1, CAST(0x0000A62200BFFA12 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (74, 1, CAST(0x0000A62200C04062 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (75, 1, CAST(0x0000A62200C086B2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (76, 1, CAST(0x0000A62200C0CD02 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (77, 1, CAST(0x0000A62200C11352 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (78, 1, CAST(0x0000A62200C159A2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (79, 1, CAST(0x0000A62200C19FF2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (80, 1, CAST(0x0000A62200C1E642 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (81, 1, CAST(0x0000A62200C22C92 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (82, 1, CAST(0x0000A62200C272E2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (83, 1, CAST(0x0000A62200C2B932 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (84, 1, CAST(0x0000A62200C2FF82 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (85, 1, CAST(0x0000A62200C345D2 AS DateTime), 0) INSERT [dbo].[JPCBTimeSlots] ([ID], [BayID], [TimeSlot], [IsReserved]) VALUES (50435, 35, CAST(0x0000A62300AC3392 AS DateTime), 0)
SET IDENTITY_INSERT [dbo].[JPCBTimeSlots] OFF /****** Object: Default [DF_JPCBTimeSlots_IsReserved] Script Date: 06/11/2016 17:59:00
******/
ALTER TABLE [dbo].[JPCBTimeSlots]
ADD CONSTRAINT [DF_JPCBTimeSlots_IsReserved] DEFAULT ((0)) FOR [IsReserved]
GO
You can get the the total lengths of the timeslots by using row_number to figure out the gaps and islands then use filtering based on that.
Setup:
CREATE TABLE #TimeSlots
([X] int, [ID] int, [BaylD] int, [TimeSlot] varchar(23), [IsReserved] int)
;
INSERT INTO #TimeSlots
([X], [ID], [BaylD], [TimeSlot], [IsReserved])
VALUES
(10, 10, 1, '2016-06-11 10:35:57.980', 1),
(11, 11, 1, '2016-06-11 10:36:57.980', 1),
(12, 12, 1, '2016-06-11 10:37:57.980', 0),
(13, 13, 1, '2016-06-11 10:38:57.980', 0),
(14, 14, 1, '2016-06-11 10:39:57.980', 1),
(15, 15, 1, '2016-06-11 10:40:57.980', 1),
(16, 16, 1, '2016-06-11 10:41:57.980', 0),
(17, 17, 1, '2016-06-11 10:42:57.980', 0),
(18, 18, 1, '2016-06-11 10:43:57.980', 0),
(19, 19, 1, '2016-06-11 10:44:57.980', 0),
(20, 20, 1, '2016-06-11 10:45:57.980', 0),
(21, 21, 1, '2016-06-11 10:46:57.980', 0),
(22, 22, 1, '2016-06-11 10:47:57.980', 0),
(23, 23, 1, '2016-06-11 10:48:57.980', 0),
(24, 24, 1, '2016-06-11 10:49:57.980', 0),
(25, 25, 1, '2016-06-11 10:50:57.980', 0),
(26, 26, 1, '2016-06-11 10:51:57.980', 1),
(27, 27, 1, '2016-06-11 10:52:57.980', 1),
(28, 28, 1, '2016-06-11 10:53:57.980', 1),
(29, 29, 1, '2016-06-11 10:54:57.980', 1),
(30, 30, 1, '2016-06-11 10:55:57.980', 0),
(31, 31, 1, '2016-06-11 10:56:57.980', 0),
(32, 32, 1, '2016-06-11 10:57:57.980', 0),
(33, 33, 1, '2016-06-11 10:58:57.980', 0),
(34, 34, 1, '2016-06-11 10:59:57.980', 1),
(35, 35, 1, '2016-06-11 11:00:57.980', 1),
(36, 36, 1, '2016-06-11 11:01:57.980', 1),
(37, 37, 1, '2016-06-11 11:02:57.980', 0),
(38, 38, 1, '2016-06-11 11:03:57.980', 0),
(39, 39, 1, '2016-06-11 11:04:57.980', 0)
;
I added few more free slots to make the SQL return more rows.
The query:
select min(TimeSlot), max(TimeSlot), datediff(minute, min(TimeSlot), max(TimeSlot)) from (
select row_number() over (order by TimeSlot) as RN1, row_number() over (partition by IsReserved order by TimeSlot) as RN2, * from #TimeSlots
) X where IsReserved = 0
group by RN1 - RN2
Returned data:
Start End Duration
2016-06-11 10:37:57.980 2016-06-11 10:38:57.980 1
2016-06-11 10:41:57.980 2016-06-11 10:50:57.980 9
2016-06-11 10:55:57.980 2016-06-11 10:58:57.980 3
2016-06-11 11:02:57.980 2016-06-11 11:04:57.980 2
This of course shows the free slots, so you'll need to add 1 minute to the duration
Lets first create a temp table and fill it with some test data.
CREATE TABLE #tmpTimeSlots (ID int, TimeSlot datetime, IsReserved int);
INSERT INTO #tmpTimeSlots (ID, TimeSlot, IsReserved) VALUES
(10,'2016-06-11 10:35:00',1),(11,'2016-06-11 10:36:00',1),(12,'2016-06-11 10:37:00',0),
(13,'2016-06-11 10:38:00',0),(14,'2016-06-11 10:39:00',1),(15,'2016-06-11 10:40:00',1),
(16,'2016-06-11 10:41:00',0),(17,'2016-06-11 10:42:00',0),(18,'2016-06-11 10:43:00',0),
(19,'2016-06-11 10:44:00',0),(20,'2016-06-11 10:45:00',0),(21,'2016-06-11 10:46:00',0),
(22,'2016-06-11 10:47:00',0),(23,'2016-06-11 10:48:00',0),(24,'2016-06-11 10:49:00',0),
(25,'2016-06-11 10:50:00',0),(26,'2016-06-11 10:51:00',1),(27,'2016-06-11 10:52:00',1),
(28,'2016-06-11 10:53:00',1),(29,'2016-06-11 10:54:00',1),(30,'2016-06-11 10:55:00',0),
(31,'2016-06-11 10:56:00',0),(32,'2016-06-11 10:57:00',0),(33,'2016-06-11 10:58:00',0),
(34,'2016-06-11 10:59:00',1),(35,'2016-06-11 11:00:00',1),(36,'2016-06-11 11:01:00',1),
(37,'2016-06-11 11:02:00',0),(38,'2016-06-11 11:03:00',0),(39,'2016-06-11 11:04:00',0);
This query should work on sql-server 2008.
Although I could only test it out on a more recent version.
WITH
Q1 AS (
select TimeSlot as time, IsReserved as flag, row_number() over (order by TimeSlot) as rn
from #tmpTimeSlots
),
Q2 AS (
select t1.time as time1, coalesce(t2.time,getdate()) as time2, t1.flag as flag1, coalesce(t2.flag,-1) as flag2,
row_number() over (order by t1.time) as rn
from Q1 t1
left join Q1 t2 on (t1.rn = t2.rn-1)
where t1.flag <> coalesce(t2.flag,-1)
)
select start_time, end_time, diff_minutes
from (
select q1.time2 as start_time, q2.time1 as end_time, DATEDIFF(minute, q1.time2, q2.time1) as diff_minutes
from Q2 q1
join Q2 q2 on (q1.rn = q2.rn-1)
where q1.flag2 = 0 and q2.flag1 = 0
) Q3
--where diff_minutes >= 4
--and start_time >= #starttime and end_time <= #endtime
order by start_time;
To criteria for the time range can be uncommented if that's required.
For the test data it will return these results:
start_time end_time diff_minutes
11.06.2016 10:37:00 11.06.2016 10:38:00 1
11.06.2016 10:41:00 11.06.2016 10:50:00 9
11.06.2016 10:55:00 11.06.2016 10:58:00 3
11.06.2016 11:02:00 11.06.2016 11:04:00 2
With Sql-server 2012 and beyond, the LEAD analytical function becomes available.
Which simplifies things a bit.
select start_time, end_time, DATEDIFF(minute, start_time, end_time) as diff_minutes
from
(
select dateadd(minute,1,time) as start_time, dateadd(minute,-1,next_time) as end_time
from
(
select TimeSlot as time, IsReserved as flag,
LEAD(TimeSlot, 1) OVER(PARTITION BY IsReserved ORDER BY TimeSlot) as next_time
from #tmpTimeSlots
) Q1
where flag = 1
) Q2
where start_time < coalesce(end_time,getdate())
--and DATEDIFF(minute, start_time, end_time) >= 4
--and start_time >= #starttime and end_time <= #endtime
order by start_time;