How to get the Year in between two dates - sql-server-2008

I have
leave table
EmpNo
EmpName
LeaveStart
LeaveEnd
I want to show the leave taken by year and i used datediff(dd,LeaveStart,LeaveEnd)
it will shows the no. of days have taken.
but i want to show yearly wise.
E.g
2014 - 10 days
2015 - 16 days
how & where i can use year function becoz have leavestart & leaveend
suppose if employee taken a leave
LeavStart- 28-Dec-2015
LeaveEnd - 05-Jan-2016
then result should
2015 - 4 days
2016 - 5 days
then how to use query.
please help on this

May be something like this
SELECT Year(LeaveStart),YEAR(LeaveEnd),DATEDIFF(DAY, MIN(LeaveStart), Max(LeaveEnd))
FROMtbl_Subject_OrderAssignedDetails
GROUP BY Year(LeaveStart),YEAR(LeaveEnd)

Related

Grouping Sales into non-calendar months

I am working on a database which includes sales information; the table for this is fairly basic:
ContractID(PK), CustomerID(FK), SalesAgent(FK), Value(int), SalesDate(Date)
And I have a requirement to produce a monthly sales report - sounds simple; group the dates by month.
However, the client has a non-calendar monthly sales structure - effectively, most months are 28 days, December is 42 days, and April & August are 35 days - this means that all months start on a Monday, and the extra weeks are allocated to Easter, High Summer, and Christmas, when business is usually slower.
So effectively I have a calendar like this:
Month. StartDate, EndDate
1. 20210104, 20210131
2. 20210201, 20210228
3. 20210301, 20210328
4. 20210329, 20210502
5. 20210503, 20210530
6. 20210531, 20210627
7. 20210628, 20210725
8. 20210726, 20210829
9. 20210830, 20210926
10. 20210927, 20211024
11. 20211025, 20211121
12. 20211122, 20220102
13. 20220103, 20220130
14. 20220131, 20220227
etc.
What's the best way to allocate each sale to a period above to group for reporting - I was initially thinking of having the above table as a CTE within my query, then SELECT based on the SalesDate being before and after the start and End Dates in the above, but what join do I then use to link that to the main query?
Is there no way around this other than to run the query for each specific period as listed above, or can this be done with a UNION?
(hope this makes sense)
Join your sales data and calendar, template
with calendar(Month, StartDate, EndDate) as(
..
)
select ..
from calendar
join sales on sales.date between calendar.StartDate and calendar.EndDate
group by .. calendar.Month ..

MySQL range between dates: First order + 6 months

I'm using MySQL Workbench to run my query.
I want to run a couple of different date queries, I don't know if it's possible in SQL.
1) Run the report from the first date in the system to X date.
How can I find what the first orderID or date is as part of the calculations?
I know that if I have the date to begin with, I can use:
where T5.date_purchased BETWEEN '2005-01-01' AND '2015-12-31' OR:
where T5.date_purchased BETWEEN '2005-01-01' AND CURDATE() + INTERVAL 1 DAY
UPDATE
----- Query 2 has been answered (although open to any improvement) -----
2) Run the report from the first time a product shows up, to + 6 months (to see it's first 6 months of order) ie: Widget 1 (first order) + 6 months from order date. Something like:
where widget=widgetID AND date between widget1's first purchase and +6 months
Update: This doesn't work, however this is somewhat of what I was thinking:
where (T3.products_id = 39) and DATE_ADD((T1.products_date_added), INTERVAL 1 MONTH)
I would use my P3.products_date_added, however, I don't know how to use it as part of the above, correctly.
Are either of these possible, I know how to pull the records when I know the date, I just don't know if it can be done with 'date unknown' or if I have to run a "pre-report" first. Or is it a post processing filter in excel?
Thank you in advance.
Answering problem #2:
2) Run the report from the first time a product shows up, to + 6 months (to see it's first 6 months of order) ie: Widget 1 (first order) + 6 months from order date. Something like:
where widget=widgetID AND date between widget1's first purchase and +6 months
Answer:
-- Use for specific comparisons of products OR for the first X months of sales
where (T3.products_id = 39) and T5.date_purchased between T1.products_date_added and DATE_ADD((T1.products_date_added), INTERVAL 2 MONTH)
-- This results in PID: release: 10th July, +2 months; 10th Sep. 31 units.
OR
-- (T3.products_id = 11 or T3.products_id = 39) gives the results of the 2 product orders from release date to the first 2 months of each
-- (T3.products_id) gives all products, their first 2 months of release
-- (T3.products_id = 39) gives specific product release sales
-- Inspired by: http://stackoverflow.com/questions/28788691/mysql-range-between-dates-first-order-6-months?noredirect=1#comment45853546_28788691
If it is possible for your solution, try and run 2 separate queries:
- ONE for finding the date of first order
- then calculate +6 months from query 1 result
- AND the second one to get the purchases BETWEEN both dates

Grouping months by quarter over multiple years depending on a dynamic start month

Using MySQL and PHP I am building a JSON array to populate a data table.
For the purposed of my question suppose the data table has the following columns:
Year: 2010,2011,2012,2013...<br/>
Month: 1,2,3,4,5...<br/>
Value: 100, 150, 200 etc...<br/>
The table structure cannot be altered and my solution needs come into the MySQL query
The data can be viewed either monthly, quarterly or yearly. Monthly and yearly is achieved easily through grouping by year and month.
Quarterly data can be grouped by calendar quarter (Jan-Mar, Apr-Jun, Jul-Sep, Oct-Dec) by this group statement:
GROUP BY year, round((month/3)+0.3,0)
So where Jan, Feb and March might all have 100 for their value the summed result is 300, same for other months.
Now my problem comes when I want to group values by a financial quarter, for example a quarter that starts in Feb, or any other quarters.
I have a statement that works for the quarter grouping using two variables that can be accessed via the SQL query, start_year (i.e. 2014) and start_month (i.e. 2)
GROUP BY year, (((round(((((month-(start_month-1))+((year-start_year)*12))-((year-start_year)*12))/3)+0.33,0)/4)+4)-floor(((round(((((month-(start_month, '%m')-1))+((year-start_year)*12))-((year-start_year*12))/3)+0.33,0)/4)+4)))*12
which basically will assign a 0,3,6,9 value to each calendar month for the purposes of grouping.
In the financial year starting February this works fine for quarters 1-3, however breaks for the final quarter as it includes Nov and Dec 2014 data and Jan from 2015.
As a result I get 5 rows of data instead of 4.
This is because of the preceding GROUP by year clause, an important addition as we might want to generate a table that views sequential quarters for multiple years.
So what I am looking for is a way of grouping the years together by offsetting the start month.
So when the year starts in Jan it will group Jan-Dec but if we change that to starting Feb it will group Feb-Jan.
Any ideas, suggestions most welcome!
Regards,
Carl
I solved a similar problem just now (a Moodle report aggregating assignment scores by year and quarter) with something like this:
select year(from_unixtime(s.timemarked)) as year, quarter(from_unixtime(s.timemarked)) % 4 + 1 as quarter, count(distinct data1) as "tickets graded" from mdlassignment_submissions s where grade >= 0 group by year, quarter order by year, quarter;
The relevant part for what you're doing is quarter(from_unixtime(s.timemarked)) % 4 + 1 as quarter
As another commenter pointed out, MySQL has a quarter() function, but it doesn't do financial quarters. However, since (as I understand it, at least, based on consulting the relevant wikipedia page) financial quarters are just offset by 1, the % 4 + 1 at the end should convert it.

Range query from month and year

I have a table like this:
ID month year content
1 4 2013 xxxxx
2 5 2013 yyyyy
3 6 2013 zzzzz
4 8 2014 fffff
I want to query it based on a year and month range.
I have query like this:
SELECT * FROM UPP
WHERE ( month = '4' AND year = '2013' )
AND ( month = '6' AND year = '2013' )
That query runs but returns no result. Can anyone help me for fix this query?
NB: The month and year columns are integers.
Why not use the correct data type?
Failing that:
SELECT * FROM UPP WHERE (year=2013) AND (month BETWEEN 4 AND 6);
Would be the easiest path to this particular answer.
EDIT
SQL Fiddle for reference.
There will never be any rows where both month=4 and month=6 which is what your query is asking for. Adding brackets like that will not alter the AND behaviour as you seem to want them to so you are asking for WHERE year=2013 AND month=4 AND month=6.
There are a number of ways you could ask for what you seem to be wanting, for instance:
WHERE (year=2013 AND month=4) OR (year=2013 AND month=6)
or
WHERE year=2013 AND (month=4 OR month=6)
or
WHERE year=2013 AND month IN (4,6)
If you want the full range (the full quarter, months 4, 5, and 6 not just months 4 and 6 then swasheck's suggestion is probably the clearest way to go, though this will fall down if the date range straddles a boundary between years. If you need to do fully flexible ranged queries ("the six months to February 2013" and so forth) then you might want to rethink the table structure to more easily/efficiently support that.

MSAccess - Design query to group by anniversary date

Lets say I have a table with these fields
LeaveDate
LeaveType
I want to write a query that groups by an annivesary date.
For example say 8th Feb.
So for this year any dates after 8 Feb would be "2010" and any dates before 8 Feb would show "2009".
I want this to occur for all years data.
Understand??
Malcolm
Here is how I did it
SELECT Year([tblFoo]![Leave_date])-IIf(DateDiff("d",[tblFoo]![Leave_date],DateSerial(Year([tblFoo]![Leave_date]),2,8))>0,1,0) AS Year_group, Count(tblFoo.ID) AS CountOfID
FROM tblFoo
GROUP BY Year([tblFoo]![Leave_date])-IIf(DateDiff("d",[tblFoo]![Leave_date],DateSerial(Year([tblFoo]![Leave_date]),2,8))>0,1,0);
This counts the number of records for each “Year”. We use something similar for working out birthday years which change from person to person. In that case use can just replace the fixed 2 and 8 with the month and day they were born
You could create a query with a calculated column for anniversary date, then group by that column.