Range rows from SQL Server - sql

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.

Related

get drive period and stop period from gps Table

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

Delete data based on a column and latest date

In the below Table, i need to get the query for table to Get the Delete query to remove the Unique Employee based on the older date of joining.
The result should have unique EmpNo, where the Doj is latest.
Below is the table data query
DECLARE #TableTest TABLE (
[Sid] [int] NULL,
[EmpNo] [int] NULL,
[EmpName] [nvarchar](50) NULL,
[DoJ] [int] NULL
)
INSERT INTO #TableTest VALUES
(101,'Suresh',20160517)
,(102,'Ravi',20160312)
,(101,'Ramu',20161022)
,(103,'Kumar',20160308)
,(104,'Gopi',20160411)
,(104,'Sridhar',20160620)
,(104,'Suresh',20161012)
Expected result
If you want to delete the rows, you can do:
with todelete as (
select tt.*,
row_number() over (partition by EmpNo order by Sid desc) as seqnum
from #tabletest
)
delete from todelete
where seqnum <> 1;

How to write trigger to generate sequence number for repeated value

I need to generate sequence number for repeated value in a SQL Server table.
Here's my table
CREATE TABLE [dbo].[tbl_all_purple_flag_level](
[Sno] [int] IDENTITY(1,1) NOT NULL,
[Id] [varchar](50) NULL,
[Name] [varchar](50) NULL,
[Score] [varchar](50) NULL,
[Disability_Level] [varchar](50) NULL,
[visited_count] [varchar](50) NULL,
[Date] [varchar](50) NULL
)
If id has repeated numbers, I need visited_count to be a sequence number (1, 2, 3...)
I tried this code
SELECT
id,
RIGHT('0'+ CAST((ROW_NUMBER() OVER (Partition By id Order By id)) as varchar(2)), 2) as duplicate_id
FROM
tbl_all_purple_flag_level
It works fine but I don't know how to do in trigger. Can anyone help me? Thanks!
ALTER TRIGGER tr_After_Update_Inser
ON [dbo].[tbl_all_purple_flag_level]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
WITH Updateable
AS
(
SELECT [Sno], id, [visited_count],
RIGHT('0'+ CAST((ROW_NUMBER() OVER (Partition By id Order By id, [Date] DESC)) as varchar(2)), 2) as duplicate_id
FROM tbl_all_purple_flag_level
)
UPDATE Updateable
SET [visited_count] = duplicate_id
END
One thing I would like to point out, SQL Server has Data types to store almost all kinds of data, I can see you are saving Dates in Varchar data type and IDs and Score all in varchar data type, Sql Server has Date data type to store date values. why would you use varchar for all the columns dont know but I think you should consider using appropriate data types for your column instead of using VARCHAR for everything.

Subquery Performance - Non Unique Column in Where Clause

I have two tables
Table Jobs
[ID] [int] IDENTITY(1,1) NOT NULL,
[title] [varchar](150) NULL,
[description] [text] NULL
Table JobSkills
[id] [int] IDENTITY(1,1) NOT NULL,
[jobId] [int] NULL,
[skill] [varchar](150) NULL
Shown above partial list of columns.
For table JobSkills I have indexed jobId column, column skill is full text indexed.
I have a stored procedure to get the list of jobs. sort of like this.
Select totalItems
,Id,title
from
(
Select Row_Number() over(Order By
CASE WHEN #sortBy Is Not Null AND #sortBy='relevance'
THEN
SkillMatchRank
END DESC
,CASE WHEN #sortBy Is Not Null AND #sortBy='date' THEN CreateDate END DESC
) As rowNumber
,COUNT(*) OVER() as totalItems
,ID,createDate,title
from Jobs J
OUTER APPLY dbo.GetJobSkillMatchRank(J.ID,#searchKey) As SkillMatchRank
Where
--where conditions here
) tempData
where
rowNumber>=CASE WHEN #startIndex>0 AND #endIndex>0 THEN #startIndex ELSE rowNumber END
AND rowNumber<=CASE WHEN #startIndex>0 AND #endIndex>0 THEN #endIndex ELSE rowNumber END
I have created a inline table valued function to get the skill matching rank.
CREATE FUNCTION [dbo].[GetJobSkillMatchRank]
(
#jobId int,
#searchKey varchar(150)
)
RETURNS TABLE
AS
RETURN
(
select SUM(ISNULL(JS2.[Rank],0)) as rank
from FREETEXTTABLE(JobSkills,skill,#searchKey) JS2
Where JS2.[Key] in (Select ID from JobSkills Where jobId=#jobId)
)
GO
Problem
Query runs super slow, more then a minute.
My observation
For the table valued function if I set jobId=1 (I do have a job with id=1) then it performs super fast as desired.
I understand that jobId is not unique column on JobSkills table.
In this case how could I improve the performance???
UDFs are great in certain cases, but the execution plans don't get cached like sprocs do. If you try using another derived table instead of a function, the query might perform better.

what's the right way of joning two tables, group by a column, and select only one row for each record?

I have a crews table
CREATE TABLE crew(crew_id INT, crew_name nvarchar(20), )
And a time log table, which is just a very long list of actions performed by the crew
CREATE TABLE [dbo].[TimeLog](
[time_log_id] [int] IDENTITY(1,1) NOT NULL,
[experiment_id] [int] NOT NULL,
[crew_id] [int] NOT NULL,
[starting] [bit] NULL,
[ending] [bit] NULL,
[exception] [nchar](10) NULL,
[sim_time] [time](7) NULL,
[duration] [int] NULL,
[real_time] [datetime] NOT NULL )
I want to have a view that shows only one row for each crew with the latest sim_time + duration .
Is a view the way to go? If yes, how do I write it? If not, what's the best way of doing this?
Thanks
Here is a query to select what you want:
select * from (
select
*,
row_number() over (partition by c.crew_id order by l.sim_time desc) as rNum
from crew as c
inner join TileLog as l (on c.crew_id = l.crew_id)
) as t
where rNum = 1
it depends on what you need that data for.
anyway, a simple query to find latest sim time would be something like
select C.*, TL.sim_time
from crew C /*left? right? inner?*/ join TimeLog TL on TL.crew_id = C.crew.id
where TL.sim_time in (select max(timelog_subquery.sim_time) from TimeLog timelog_subquery where crew_id = C.crew_id )