get drive period and stop period from gps Table - sql

I have a table which contains gps data.
It saves a record every 30 Seconds
A record contains speed (float), CurrTime (datetime) and CarID (int)
How can I get (for each car and day) those values :
total drive period
total stop period
Stop means its speed must be <5 for continous 15 minutes
For example :
car1 on 7/7/2017
stopped for 10 Hours
drive for 14 hours
Table Definition
CREATE TABLE [dbo].[T_Tracking](
[id] [int] ,
[IMEI] [nvarchar](50) NULL,
[TrackTime] [datetime] NULL,
[CurrTime] [datetime] NULL CONSTRAINT [DF_T_Tracking_CurrTime] DEFAULT (getutcdate()),
[Longitude] [nvarchar](50) NULL,
[Lattitude] [nvarchar](50) NULL,
[speed] [float] NULL,
[SafeAreaID] [int] NULL,
[GeoFenceID] [int] NULL,
[CarID] [int] NULL,
[Country] [nvarchar](50) NULL,
[City] [nvarchar](50) NULL,
[Area] [nvarchar](50) NULL,
[Street] [nvarchar](50) NULL,
[FullAddress] [nvarchar](150) NULL,
[Distance] [float] NULL )
This SQLFiddle is auto-populated with table definition and some data examples
(Parking)
To ignore trafic stops
Data Examples
Expected Data
CarName Date DrivePeriod StopPeriod
Car1 7/7/2017 16 8
Car2 7/7/2017 14 10
car3 7/7/2017 12 12
car1 6/7/2017 15 9
My try
SELECT carid
,sum( LAG( TrackTime, 1, Null) OVER (PARTITION BY carid ORDER BY carid)- TrackTime)
FROM T_Tracking
group by carid
Error encountered
Msg 8120, Level 16, State 1, Line 2
Column 'T_Tracking.TrackTime' is
invalid in the select list because it is not contained in either an
aggregate function or the GROUP BY clause.
Msg 4109, Level 15, State 1, Line 2
Windowed functions cannot be used in the context of another
windowed function or aggregate.
Try 2
SELECT
carid
, TrackTime
, LAG( TrackTime, 1, Null) OVER (PARTITION BY carid ORDER BY carid) as trackold
, CONVERT(date, TrackTime) as TrackDay
, speed,DATEDIFF(minute, LAG( TrackTime, 1, Null) OVER (PARTITION BY carid ORDER BY carid),TrackTime)
FROM T_Tracking
result
the problem here when the lag record on another day it get wrong subtarction
i need to put a contition to be in the same day

Build a CTE that calculates for each column if it is considered as stopped or not
+ a GROUP BY YEAR(CurrTime), MONTH(CurrTime), DAY(CurrTime), CarId, Stopped will do the job.
Then you only have to SUM() the amount of time between a current record time
and its LAG() value and it's done.
WITH CTE "Common Table Expression" (starting with SQL Server 2008)
GROUP BY (starting with SQL Server 2008)
SUM Function (starting with SQL Server 2008)
LAG Function (starting with SQL Server 2012)
Easy to tell, that if you are under SQL Server 2008 this will be very tricky to achieve.
If you are under SQL Server 2012 you can replace the LAG function with a sub-select for example.
Example of query
WITH Stopped
AS
( CTE_query_definition )
SELECT
YEAR(CurrTime)
,MONTH(CurrTime)
,DAY(CurrTime)
,CarID
,Stopped
,SUM(CurrTime - LAG(CurrTime) OVER ( order_by_clause ))
FROM [dbo].[T_Tracking]
GROUP BY YEAR(CurrTime),MONTH(CurrTime),DAY(CurrTime),CarID,Stopped
Then you just have to replace ( CTE_query_definition) and order_by_clause to achieve your goal

Related

SQL Server - Operand type clash: numeric is incompatible with datetimeoffset

i am having issue with passing the data from one table to another due to data type.
I tried converting datetimeoffset into date, and inserting into table where i have it as date type and im still getting this error.
this is the format of date/time i have:
2018-12-12 13:00:00 -05:00 in one table, and i have to just pars time and insert it into new table. I tried with casting using ,
CAST([from] AS date) DATE_FROM
I can run the query as select and it works but the moment i try to insert the data into other table even if the other table is formatted and prepared as date type i still get the issue.
Here is the table that stored data with datetimeoffset:
[dbo].[tmp_count](
[elements_Id] [numeric](20, 0) NULL,
[content_Id] [numeric](20, 0) NULL,
[element_Id] [numeric](20, 0) NULL,
[element-name] [nvarchar](255) NULL,
[sensor-type] [nvarchar](255) NULL,
[data-type] [nvarchar](255) NULL,
[from] [datetimeoffset](0) NULL,
[to] [datetimeoffset](0) NULL,
[measurements_Id] [numeric](20, 0) NULL,
[measurement_Id] [numeric](20, 0) NULL,
[from (1)] [datetimeoffset](0) NULL,
[to (1)] [datetimeoffset](0) NULL,
[values_Id] [numeric](20, 0) NULL,
[label] [nvarchar](255) NULL,
[text] [tinyint] NULL
And I am trying to cast columns with datetimeoffset to date and time and push it to #tmp1 table with
SELECT [elements_Id]
,[content_Id]
,[element_Id]
,[element-name]
,[sensor-type]
,[data-type]
,CAST([from] AS date) DATE_FROM
,[to]
,[measurements_Id]
,[measurement_Id]
,CAST([from (1)] AS time (0)) TIME_FROM
,CAST([to (1)] AS TIME(0)) TIME_TO
,[values_Id]
,[label]
,[text]
INTO #Tmp1
FROM [VHA].[dbo].[tmp_count]
SELECT
FROM #tmp1
which gives me the time in format for DATE_FROM as 2018-12-12 and for the DATE_FROM and DATE_TO as 13:00:00 which is exactly what i need.
Now i am trying to splice this table with another table and push it in final table that looks like this:
[dbo].[tbl_ALL_DATA_N](
[serial-number] [nvarchar](255) NULL,
[ip-address] [nvarchar](255) NULL,
[name] [nvarchar](255) NULL,
[group] [nvarchar](255) NULL,
[device-type] [nvarchar](255) NULL,
[elements_Id] [numeric](20, 0) NULL,
[content_Id] [numeric](20, 0) NULL,
[element_Id] [numeric](20, 0) NULL,
[element-name] [nvarchar](255) NULL,
[sensor-type] [nvarchar](255) NULL,
[data-type] [nvarchar](255) NULL,
[DATE_FROM] [date] NULL,
[to] [datetimeoffset](0) NULL,
[measurements_Id] [numeric](20, 0) NULL,
[measurement_Id] [numeric](20, 0) NULL,
[TIME_FROM] [time](0) NULL,
[TIME_TO] [time](0) NULL,
[values_Id] [numeric](20, 0) NULL,
[label] [nvarchar](255) NULL,
[text] [tinyint] NULL
using query below:
INSERT INTO [dbo].[tbl_ALL_DATA_N]
([serial-number],
[ip-address],
[name],
[group],
[device-type],
[measurement_id],
TIME_FROM,
TIME_TO,
[content_id],
[elements_id],
[element-name],
[sensor-type],
[data-type],
DATE_FROM,
[to],
[element_id],
[measurements_id],
[values_id],
[label],
[text])
SELECT *
FROM [VHA].[dbo].[tmp_sensor_info] A
FULL OUTER JOIN #tmp1 B
ON 1 = 1
And here is another message im getting: Msg 206, Level 16, State 2, Line 25
Operand type clash: numeric is incompatible with time
Any ideas?
The solution, which #PanagiotisKanavos alluded to in the comments, is to explicitly list the columns in your final SELECT * FROM.... The order of the columns in that SELECT statement aren't lining up with the columns you're INSERTing into in the destination table.
You may need to run an ad hoc instance of the query to sort out the column order. And then do yourself a favor for future maintenance and be sure to include a table alias on all of the listed columns so you (or whoever has to look at the code next) can easily find out if data is coming from [VHA].[dbo].[tmp_sensor_info] or #tmp1.
This is just one of many dangers in using SELECT * in production code. There's a ton of discussion on the issue in this question: Why is SELECT * considered harmful?
Also, as long as you're in there fixing up the query, consider meaningful table aliases. See: Bad habits to kick : using table aliases like (a, b, c) or (t1, t2, t3).

Output data from current month?

I have this table and i want to ge the data from current month.
This is the table:
CREATE TABLE [dbo].[CSEReduxResponses](
[response_id] [int] IDENTITY(1,1) NOT NULL,
[submitterdept] [int] NOT NULL,
[commentdate] [datetime] NOT NULL,
[status] [int] NOT NULL,
[approvedby] [int] NULL,
[approveddate] [datetime] NULL,
[execoffice_approvedby] [int] NULL,
CONSTRAINT [PK_CSE_Responses] PRIMARY KEY CLUSTERED
(
I want to get the data where
status=1 and execoffice_status=0 and the current date.I want to use the approveddata column to get the date.
Right now I have
select * from CSEReduxResponses WHERE STATUS=1 AND EXECOFFICE_STATUS=0;
I have Microsoft sql server 2008
Microsoft SQL Server Management Studio 10.0.2531.0
Add AND MONTH([approveddate]) = MONTH(GETDATE()) AND YEAR([approveddate]) = YEAR(GETDATE()) to your where clause, assuming [approveddate] is the date you're interested in.
It is simple:
SELECT *
FROM CSEReduxResponses
WHERE STATUS = 1
AND EXECOFFICE_STATUS = 0;
AND MONTH(commentdate) = MONTH(GETDATE())
AND YEAR(commentdate) = YEAR(GETDATE())

Range rows from SQL Server

I want to create paging using T-SQL. How can I select 10 rows from 11th row to 20th row?
I know I can do this with C# etc. But my question is about SQL Server.
Here is the table:
CREATE TABLE EarlyAccess(
[EarlyAccessUserId] [int] IDENTITY(1,1) NOT NULL,
[FirstName] [nvarchar](50) NOT NULL,
[Lastname] [nvarchar](50) NOT NULL
)
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY earlyAccessUserId) rn
FROM earlyAccess
) q
WHERE rn BETWEEN 11 AND 20
ORDER BY
earlyAccessUserId
There is not such thing as n'th record in SQL unless you explicitly specify ordering.

how to have a column count the number of times a BIT field is zero and another column counting the number of time it is one?

I have the following table:
CREATE TABLE [dbo].[PartsWork](
[parts_work_id] [int] IDENTITY(1,1) NOT NULL,
[experiment_id] [int] NOT NULL,
[partition_id] [int] NULL,
[part_id] [int] NOT NULL,
[sim_time] [int] NULL,
[real_time] [datetime] NULL,
[construction] [bit] NULL,
[destruction] [bit] NULL,
[duration] [int] NULL )
I want to write a SQL that outputs the part_id, number of times construction is = 1 and number of times destruction is = 1 for a given experiment_id AND partition_id.
I can do this using multi-statement table valued functions and a loop, but I would like to be able to do this in a single SQL. Is this possible?
To give all part_id values, you need the OVER clause on the COUNT (this is an inline aggregation without using GROUP BY)
SELECT
part_id,
COUNT(CASE WHEN construction = 1 THEN 1 END) OVER () AS CountConstructionIs1,
COUNT(CASE WHEN destruction = 1 THEN 1 END) OVER () AS CountDestructionIs1
FROM
[dbo].[PartsWork]
WHERE
experiment_id = #experiment_id
AND
partition_id = #partition_id
See MSDN for more

Order by Month in SQL server 2008

I want to order my table based on month. .. But the thing is order by month during the fiscal year... ie., April to march .
thanks in advance
You can order by anything you can write an expression for... In your case
Try:
... Order By (Month(somedate) + 8) % 12
EDIT: Should be 8 not 9...
I suggest something similar to Jakob's answer, only more along the lines of:
((month(somedate) - 4) + 12) % 12
Subtracting 4 shifts April to the beginning. Adding 12 handles pre-April months, and the modulus corrects the previous step for post-April months.
This will produce results in the range of 0 - 11. Also the x - 4 + 12 step can be simplified to x + 8; I thought I'd leave it unabbreviated for the purpose of the explanation.
A lot of the above will work, but if you find yourself doing a lot of date manipulation with different calendars it might be worth creating a separate calendar table as a lookup.
Something like
CREATE TABLE [dim].[Date](
[DateSK] [int] NOT NULL,
[Date] [datetime] NOT NULL,
[Year] [int] NOT NULL,
[Month] [int] NOT NULL,
[Day] [int] NOT NULL,
[WeekDayName] [varchar](9) NOT NULL,
[MonthName] [varchar](9) NOT NULL,
[QuarterNumber] [int] NOT NULL,
[FinancialYear] [int] NOT NULL,
[FinancialMonth] [int] NOT NULL,
[MonthLength] [int] NOT NULL,
[DaysRemainingInMonth] [int] NOT NULL,
[DaysRemainingInYear] [int] NOT NULL,
[IsLeapYear] [bit] NOT NULL,
[DaysInYear] [int] NOT NULL,
[DayOfYear] [int] NOT NULL,
etc, etc.
)
USE my_db
SELECT
MONTH(t1.expiry) as SortOrder,
DATENAME(MONTH,t1.expiry) AS ExpiryMonth,
COUNT(*) AS Count
FROM
table1 t1 LEFT JOIN table2 t2 ON t2.c1 = t1.c1
WHERE
YEAR(t1.expiry) = '2012' AND t2.c2 = 'X'
GROUP BY
MONTH(t1.expiry),
DATENAME(MONTH,t1.expity)
ORDER BY
SortOrder ASC
I guess a more generic solution like this one is better than always using a custom sort. There is not much cost involved in terms of processing time.
SELECT
Column1,
Column2,
Column3,
SomeDate,
CASE MONTH(SomeDate)
WHEN 4 THEN 1
WHEN 5 THEN 2
WHEN 6 THEN 3
WHEN 7 THEN 4
WHEN 8 THEN 5
WHEN 9 THEN 6
WHEN 10 THEN 7
WHEN 11 THEN 8
WHEN 12 THEN 9
WHEN 1 THEN 10
WHEN 2 THEN 11
WHEN 3 THEN 12
END as FiscalMonth
FROM myTable
ORDER BY FiscalMonth
How about this:
SELECT ...
ORDER BY MONTH(SomeDate) % 4