Order by Month in SQL server 2008 - sql

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

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

getting wrong results in count function while using group by clause in sql server

im calculating how many links are submitted in each categories. i have assigned four categories -Classifieds,Events,Articles,Socialbookmarking for monday . user submitted 15 links in classified category . but it showing 15*4 = 60 links submitted.
output getting like this
Categoryname DayTarget LnkSubmsnDate LnkSubmtdBy submittedLinks performance
Classifieds 15 10/12/2015 swapna 60 Reached
but i want like this
Categoryname DayTarget LnkSubmsnDate LnkSubmtdBy submittedLinks performance
Classifieds 15 10/12/2015 swapna 15 Reached
Events 2 10/12/2015 swapna 0 not Reached
Articles 2 10/12/2015 swapna 0 not Reached
Socialbookmarking 10 10/12/2015 swapna 0 not Reached
sql query
select c.Categoryname,DayTarget,l.LnkSubmsnDate,l.LnkSubmtdBy,COUNT(LinkId) as submittedLinks,
(CASE
WHEN DayTarget=COUNT(LinkId) THEN 'Reached'
WHEN DayTarget-COUNT(LinkId) < 1 THEN 'Reached'
WHEN DayTarget-COUNT(LinkId) >= 1 THEN 'Not Reached'
END ) as performance
from tbl_Link as l
join Tbl_DaySubmission ds on l.ProjectId=ds.projectid and l.CategoryId=ds.CatId
join tbl_Category c on l.CategoryId=c.CategoryId
where LnkSubmsnDate='2015-10-12'and l.ProjectId='109'
group by c.Categoryname,ds.DayTarget,LnkSubmsnDate,l.LnkSubmtdBy
table definations
TABLE [dbo].[Tbl_DaySubmission](
[DayId] [bigint] IDENTITY(100,1) NOT NULL,
[DayName] [varchar](50) NOT NULL,
[DayNumber] [int] NOT NULL,
[CatId] [int] NULL,
[DayTarget] [int] NOT NULL,
[ProjectID] [int] NULL,
[status] [bit] NULL
tbl_link
TABLE [dbo].[tbl_Link](
[LinkId] [bigint] IDENTITY(1,1) NOT NULL,
[LinkName] [nvarchar](255) NULL,
[ReportLinks] [nvarchar](255) NULL,
[CreatedDate] [nvarchar](255) NULL,
[CategoryId] [int] NULL,
[KeywordID] [int] NULL,
[ProjectId] [int] NULL,
[LnkSubmsnDate] [date] NULL,
[LnkSubmtdBy] [nvarchar](255) NULL,
tbl_category
TABLE [dbo].[tbl_Category](
[CategoryId] [int] IDENTITY(1,1) NOT NULL,
[Categoryname] [varchar](50) NOT NULL
if you are getting answers in multiples of the expected value, it means that your join is not working properly (Data is not as you expected in one of the table).
We cannot guide you without seeing the actual data in all of the tables as you are not using the primary keys to join tables.
I would suggest you to break your query into multiple steps and evaluate the result at each step before joining with another table and that would help you in fixing it.
You can't retrieve LnkSubmsnDate and LnkSubmtdBy from unsubmitted tbl_Links. You have to set default values to the 2 columns if they are unsubmitted, otherwise they show null.
SELECT
c.Categoryname
, ds.DayTarget
, CASE WHEN (COUNT(LinkId) > 0) THEN l.LnkSubmsnDate
ELSE NULL END AS [LnkSubmsnDate]
, CASE WHEN (COUNT(LinkId) > 0) THEN l.LnkSubmtdBy
ELSE NULL END AS [LnkSubmtdBy]
, COUNT(LinkId) AS submittedLinks
, (CASE
WHEN DayTarget=COUNT(LinkId) THEN 'Reached'
WHEN DayTarget-COUNT(LinkId) < 1 THEN 'Reached'
WHEN DayTarget-COUNT(LinkId) >= 1 THEN 'Not Reached'
END ) AS performance
FROM tbl_Category AS c
INNER JOIN Tbl_DaySubmission AS ds ON ds.CatId = c.CategoryId
LEFT JOIN (SELECT * FROM tbl_Link WHERE LnkSubmsnDate='2015-10-12') AS l ON l.ProjectId = ds.ProjectID AND l.CategoryId = ds.CatId
WHERE ds.ProjectID = 109
GROUP BY c.Categoryname, ds.DayTarget, l.LnkSubmsnDate, l.LnkSubmtdBy
ORDER BY performance DESC
http://sqlfiddle.com/#!6/548a26/7

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

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 )