How to query groupby in following situation - vb.net

I have datatable in the following format
Id LocationId UserName Startdate
1 10 xz 2017-02-21 09:05:20
2 10 xz 2017-02-21 09:15:20
3 10 xz 2017-02-21 09:25:20
4 10 xz 2017-02-21 09:35:20
5 11 xy 2017-02-21 09:45:20
6 11 xy 2017-02-21 09:55:20
7 11 xy 2017-02-21 10:05:20
8 11 xy 2017-02-21 10:15:20
9 10 xz 2017-02-21 10:15:20
10 10 xz 2017-02-21 10:25:20
I want to calculate starttime end time and differnce of time ,
and have show record as
Id locationId startdate starttime endtime timespan
1 10 2017-02-21 09:05 09:35:20 0hr 30min0sec
2 11 2017-02-21 09:05 09:35:20 0hr 30min0sec
3 10 2017-02-21 10:15 10:25 0hr 10min 0sec

If you mean SQL, I hope the following can help you:
WITH TEST AS(
SELECT *,
CASE WHEN LAG(LocationId,1) OVER(ORDER BY ID) != LocationId
OR LAG(LocationId,1) OVER(ORDER BY ID) IS NULL
THEN ID
ELSE 0 END FLAG
FROM [dbo].[DATATABLE]),`
`GroupData AS(
SELECT [LocationId],[UserName],[startdate],MAX(MI.FLAG) FLAG FROM TEST JOIN
(SELECT FLAG FROM TEST
WHERE FLAG != 0) MI ON TEST.ID >= MI.FLAG
GROUP BY [ID],[LocationId],[UserName],[startdate],TEST.FLAG)`
`SELECT LocationID,MIN([startdate]),MAX([startdate]) FROM GroupData
GROUP BY FLAG,LocationID

Related

Query to roll over weekends (saturday and Sunday) to next business Day (Monday) if it is same month and

So if we start a month on a weekend the first day becomes the weekend and it should roll over to weekday and similarly Holidays should roll back to previous day.
Date RecognizedBusinessDateKey RecognizedBusinessDateNumber
7/28/2020 20200728 19
7/29/2020 20200729 20
7/30/2020 20200730 21
7/31/2020 20200731 22
8/1/2020 20200803 1
8/2/2020 20200803 1
8/3/2020 20200803 1
8/4/2020 20200804 2
Date RecognizedBusinessDateKey RecognizedBusinessDateNumber
5/28/2020 20200528 19
5/29/2020 20200529 20
5/30/2020 20200529 20
5/31/2020 20200529 20
6/1/2020 20200601 1
6/2/2020 20200602 2
6/3/2020 20200603 3
6/4/2020 20200604 4
Date RecognizedBusinessDateKey RecognizedBusinessDateNumber
6/4/2020 20200604 4
6/5/2020 20200605 5
6/6/2020 20200605 5
6/7/2020 20200608 6
6/8/2020 20200608 6
6/9/2020 20200609 7
Data is looking like this in table
I tried the below query
SELECT
d.Date
,d.DateKey
,d.IsBusinessDay
,d.MonthKey
,ISNULL(MAX(d2.DateKey),d.DateKey) AS RecognizedBusinessDateKey
,DENSE_RANK() OVER(PARTITION BY d.MonthKey ORDER BY ISNULL(MAX(d2.DateKey),d.DateKey)) AS RecognizedBusinessDateNumber
FROM dbo.DimDate d
LEFT JOIN dbo.DimDate d2
ON d2.MonthKey <= d.DateKey
WHERE d2.IsBusinessDay = 'Business Day'
AND d2.DateKey > 0
AND d2.Date BETWEEN '8/1/2020' AND '8/31/2020'
GROUP BY
d.Date
,d.DateKey
,d.IsBusinessDay
,d.MonthKey

SQL Server 2012. Incrementing a integer based on the difference of row x+1 - row x

I have a scenario in sql server which I would really appreciate your help. I have 4 columns (ID to rownum) and 1 column (bindex) that I would like to calculate. These are detailed below
ID StartDate EndDate rownum bindex
A 27/06/2020 12:00 27/06/2020 16:48 1 1
A 27/06/2020 16:48 27/06/2020 21:36 2 1
A 02/07/2020 09:36 04/07/2020 09:36 3 2
A 06/07/2020 09:36 06/07/2020 21:36 4 3
A 06/07/2020 22:00 06/07/2020 23:58 5 3
A 07/07/2020 09:36 07/07/2020 21:36 6 3
A 08/07/2020 09:36 09/07/2020 09:36 7 3
A 11/07/2020 09:36 12/07/2020 09:36 8 4
What I am looking to do is increment the bindex variable by 1 where the startdate of row x+1 - enddate of row x is >=1. The first record would have a bindex value of 1 and then increment this by 1 for all the remaining rows until another break>=1 day is found.
Is there any easy way to do this in a cte or a simple looping structure that I've missed?
Many Thanks
Use lag() and a cumulative sum:
select t.*,
sum(case when prev_enddate >= dateadd(day, -1, startdate) then 0 else 1 end) over (partition by id order by rownum) as bindex
from (select t.*, lag(enddate) over (partition by id order by rownum) as prev_enddate
from t
) t;

Restart Row Number Based on Date and Increments of N

I have a table with the following data that I generated with a date table
date day_num (DAY_NUM % 7)
2019-07-09 0 0
2019-07-10 1 1
2019-07-11 2 2
2019-07-12 3 3
2019-07-13 4 4
2019-07-14 5 5
2019-07-15 6 6
2019-07-16 7 0
I basically want to get a week number that restarts at 0 and I need help figuring out the last part
The final output would look like this
date day_num (DAY_NUM % 7) week num
2019-07-09 0 0 1
2019-07-10 1 1 1
2019-07-11 2 2 1
2019-07-12 3 3 1
2019-07-13 4 4 1
2019-07-14 5 5 1
2019-07-15 6 6 1
2019-07-16 7 0 2
This is the sql I have so far
select
SUB.*,
DAY_NUM%7
FROM(
SELECT
DISTINCT
id_date,
row_number() over(order by id_date) -1 as day_num
FROM schema.date_tbl
WHERE Id_date BETWEEN "2019-07-09" AND date_add("2019-07-09",146)
Building on your query:
select SUB.*, DAY_NUM%7,
DENSE_RANK() OVER (ORDER BY FLOOR(DAY_NUM / 7)) as weeknum
FROM (SELECT DISTINCT id_date,
row_number() over(order by id_date) -1 as day_num
FROM schema.date_tbl
WHERE Id_date BETWEEN "2019-07-09" AND date_add("2019-07-09", 146)
) x

Creating a new calculated column in SQL

Is there a way to find the solution so that I need for 2 days, there are 2 UD's because there are June 24 2 times and for the rest there are single days.
I am showing the expected output here:
Primary key UD Date
-------------------------------------------
1 123 2015-06-24 00:00:00.000
6 456 2015-06-24 00:00:00.000
2 123 2015-06-25 00:00:00.000
3 658 2015-06-26 00:00:00.000
4 598 2015-06-27 00:00:00.000
5 156 2015-06-28 00:00:00.000
No of times Number of days
-----------------------------
4 1
2 2
The logic is 4 users are there who used the application on 1 day and there are 2 userd who used the application on 2 days
You can use two levels of aggregation:
select cnt, count(*)
from (select date, count(*) as cnt
from t
group by date
) d
group by cnt
order by cnt desc;

Extract first ocurrence of an item in column A based on column B using SQL

I have the following data, and I would like to create a result set that includes the rows that are the change in Item and the first ocurrence of Code == 1. Note that the first Code seen after a chnage in Item does not always have to be 1 (see the *):
The input data:
DateTime Item Code
*2016-12-02 16:34:00 1 1
2016-12-02 16:35:00 1 4
2016-12-02 16:36:00 1 1
2016-12-02 16:37:00 1 1
2016-12-02 16:38:00 1 7
2016-12-02 16:39:00 1 5
2016-12-02 16:40:00 1 6
2016-12-02 16:41:00 2 5
*2016-12-02 16:42:00 2 1
2016-12-02 16:43:00 2 4
2016-12-02 16:44:00 2 1
2016-12-02 16:45:00 2 5
2016-12-02 16:46:00 2 8
2016-12-02 16:47:00 2 1
2016-12-02 16:48:00 5 7
2016-12-02 16:49:00 5 7
*2016-12-02 16:50:00 5 1
2016-12-02 16:51:00 5 1
2016-12-02 16:52:00 5 4
2016-12-02 16:53:00 5 3
*2016-12-02 16:54:00 1 1
2016-12-02 16:55:00 1 1
2016-12-02 16:56:00 1 1
2016-12-02 16:57:00 1 8
2016-12-02 16:58:00 1 9
2016-12-02 16:59:00 1 3
2016-12-02 17:00:00 1 2
2016-12-02 17:01:00 1 4
Expected output data:
DateTime Item Code
*2016-12-02 16:34:00 1 1
*2016-12-02 16:42:00 2 1
*2016-12-02 16:50:00 5 1
*2016-12-02 16:54:00 1 1
I am using SQL Server 2012 Express. If anyone has recommendations of a good reference to learn these things, that would be great too.
You can use difference of ROW_NUMBERs to get the determine where the value of Item has changed and then another ROW_NUMBER from that to get the first occurrence of Code = 1:
WITH CteGrp AS(
SELECT *,
grp = ROW_NUMBER() OVER(ORDER BY Datetime) -
ROW_NUMBER() OVER(PARTITION BY Item ORDER BY Datetime)
FROM #Tbl
),
Cte AS(
SELECT *,
rn = ROW_NUMBER() OVER(PARTITION BY Item, grp ORDER BY Code, Datetime)
FROM CteGrp
)
SELECT
Datetime, Item, Code
FROM Cte
WHERE rn = 1
ORDER BY Datetime;
ONLINE DEMO
The first CTE is a common solution to Grouping Islands of Contiguous Dates. Here is an article by Jeff Moden for explanation:
Group Islands of Contiguous Dates (SQL Spackle)
WITH cte AS (
SELECT
[DateTime]
, Item
, Code
, ROW_NUMBER() OVER (PARTITION BY Item ORDER BY [DateTime]) AS RowNum
)
SELECT
[DateTime]
, Item
, Code
FROM
cte
WHERE
RowNum = 1
AND Code = 1;
Try this
select min( dateTime) dateTime, item, code from (
select dateTime, item, code from theTableName where code = 1
) code_1s
group by item, code
EDIT
To get every instance of an item where a new sequence has started .. and code = 1 is the flag for the new sequence instance ... it is a simple select statement with a where clause.
select dateTime, item, code from theTableName where code = 1