Get specific records - c#

I would like to retrieve records between September 1st 2013 to September 1st 2014
My current method gets the records from September 2014 to September 2015-
But it should be September 2013 to September 2014.
What I am doing wrong is it because i am getting DateTime.Now?
int thisYear = DateTime.Now.Year;
DateTime thisYearStart = new DateTime(thisYear, 9, 1);
DateTime thisYearEnd = thisYearStart.AddYears(1).AddTicks(-1);
command.Parameters.AddWithValue("#Date1", thisYearStart);
command.Parameters.AddWithValue("#Date2", thisYearEnd);
from this how do i select a distinct records?
WITH cte AS
(
SELECT ROW_NUMBER() OVER(ORDER BY ID, Name,SName, DOB) AS ROW, *
FROM TableName
WHERE Date > #Date1 And Date < #Date2
)
SELECT * FROM cte
WHERE ROW BETWEEN 1 AND 200

Please try to use the follwoing as your startDate and endDate.
DateTime startDate = new DateTime(DateTime.Now.Year-1,9,1);
DateTime endDate = new DateTime(DateTime.Now.Year,9,1);
command.Parameters.AddWithValue("#time", startDate);
command.Parameters.AddWithValue("#time2", endDate);
Try this one for distinct
WITH cte AS
(
SELECT DISTINCT ID, ROW_NUMBER() OVER(ORDER BY ID, Name,SName, DOB) AS ROW, *
FROM TableName
WHERE Date > #Date1 And Date < #Date2
)
SELECT * FROM cte
WHERE ROW BETWEEN 1 AND 200

Related

SQL - Get an average price of the last 7 days

I have a table that looks like this:
timestamp | commodity | amount | price |
I am trying to get the weighted average of a commodity ,for each day from the last 7 days(In order to create a graph, c# program), I managed to create a query to get the weighted average:
SELECT SUM(price * amount),
SUM(amount)
FROM [table_name]
WHERE (commodity = #commodity)
AND (timestamp >= #fromDate
AND timestamp <= #toDate);
So, I send this query 7 times, each time adding (-1) to the fromDate and toDate, to get the averages of last 7 days.
I would like to ask if there is a way to do this in 1 query, and if there is, if it can be implemented to get the same information of the last month.
you can use convert to date and do code as below:
SELECT convert(date, timestamp) as [Dates],
SUM(price * amount),
SUM(amount)
FROM [table_name]
WHERE (commodity = #commodity)
AND (timestamp >= #fromDate
AND timestamp <= #toDate)
GROUP BY convert(date, timestamp)
you have to group by date
SELECT SUM(price* amount),SUM(amount) FROM [table_name] WHERE (commodity = #commodity) AND (cast(timestamp as date)>= #fromDate AND cast(timestamp as date)<= #toDate)
Group By cast(timestamp as date)
You should to group your data by date:
SELECT SUM(price * amount),SUM(amount)
FROM [table_name]
WHERE (commodity = #commodity)
AND (timestamp >= #fromDate
AND timestamp <= #toDate)
GROUP BY CAST(timestamp as DATE);
To generate dates, you can use as below:
;with Datescte as (
Select top (datediff(day, #fromDate, #toDate) +1) Dt = Dateadd(day, Row_Number() over (order by (Select null))-1, #fromDate)
from master..spt_values s1, master..spt_values s2
), cte2 as (
SELECT convert(date, timestamp) as [Dates],
SUM(price * amount) as [Sum_Price_Amount],
SUM(amount) as [Sum_Amount]
FROM [table_name]
WHERE (commodity = #commodity)
AND (timestamp >= #fromDate
AND timestamp <= #toDate)
GROUP BY convert(date, timestamp)
)
Select Dt as [Dates] , Sum_Price_Amount, Sum_Amount
FROM Datescte d
LEFT JOIN cte2 d2
ON d.Dt = d2.Dates

How to find next (n) open days from SQL opening Hours Database

I am using a SQL database schema similar to the one found on this link.
Best way to store working hours and query it efficiently
I am storing the Opening hours for a location using this basic schema
Shop - INTEGER
DayOfWeek - INTEGER (0-6)
OpenTime - TIME
CloseTime - TIME
What i am trying to do however is for the current DateTime (i.e. today) get the NEXT (n) number of days that the shop is open. So for example if i wasnted to find the next three days that the shop was open and configured in the opening hours the shop is closed on a Sunday and todays date is 21/02/2015 (Saturday) I would like to return the days (21/02/2015)Saturday, (23/02/2015)Monday and (23/02/2015)Tuesday.
If it was Sunday i would return (23/02/2015)Monday, (24/02/2015)Tuesday and (25/02/2015)Wednesday (as its closed on sunday) and finally if it was (20/02/2015)Friday it would return (20/02/2015)Friday, (21/02/2015)Saturday, (23/02/2015)Monday.
I dont know if this is easier to do in SQL or C# but i am mentally struggling in if figuring out how to calculate this.
Any pointers, guidance would be great.
Thank you
This will give you up to 10 days ahead in a fairly efficient way. First test data:
DECLARE #DaysAhead TABLE (
Delta INT
)
INSERT INTO #DaysAhead (Delta)
SELECT 0
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
UNION ALL SELECT 10
DECLARE #Opening TABLE (
Shop INT,
DayOfWk INT,
DayNm varchar(10),
OpenTime TIME,
CloseTime TIME
)
INSERT INTO #Opening (Shop, DayOfWk, DayNm, OpenTime, CloseTime)
SELECT 1, 5, 'Fri', '09:00', '17:00' --
UNION ALL SELECT 1, 6, 'Sat' ,'09:00', '17:00'
--UNION ALL SELECT 0, 'Sun', '09:00', '17:00' -- Not open on Sunday
UNION ALL SELECT 1, 1, 'Mon', '09:00', '17:00'
UNION ALL SELECT 1, 2, 'Tue', '09:00', '17:00'
UNION ALL SELECT 1, 3, 'Wed', '09:00', '17:00'
Which can be queried like this:
DECLARE #dt datetime='21-Feb-2015'
DECLARE #dow int=datepart(dw, #dt)-1
SELECT TOP 3 o.Shop, o.DayOfWk, o.DayNm, o.OpenTime, o.CloseTime FROM (
SELECT Delta, ((#dow+Delta)%7) as DayOfWk
FROM #DaysAhead
) daysAhead
INNER JOIN #Opening o on o.DayOfWk=daysAhead.DayOfWk
ORDER BY daysAhead.Delta
Results:
DECLARE #dt datetime='20-Feb-2015' -- Fri
1 5 Fri 09:00:00.0000000 17:00:00.0000000
1 6 Sat 09:00:00.0000000 17:00:00.0000000
1 1 Mon 09:00:00.0000000 17:00:00.0000000
DECLARE #dt datetime='21-Feb-2015' -- Sat
1 6 Sat 09:00:00.0000000 17:00:00.0000000
1 1 Mon 09:00:00.0000000 17:00:00.0000000
1 2 Tue 09:00:00.0000000 17:00:00.0000000
DECLARE #dt datetime='22-Feb-2015' -- Sun
1 1 Mon 09:00:00.0000000 17:00:00.0000000
1 2 Tue 09:00:00.0000000 17:00:00.0000000
1 3 Wed 09:00:00.0000000 17:00:00.0000000
First you can use a simple query like the following to get the days of the week that the shop is open
Select DayOfWeek
From OpenHours
Where ShopId = #ShopID
This assumes that there will not be entries for days that are not open. Adjust this query if instead the open hour column is null, or less than or equal to the close time for days that are not open.
After you run that query and get the results back and preferably translate them into a List<DayOfWeek> you can do the following in your code.
List<Day0fWeek> openDays = GetOpenDaysFromDB();
DateTime start = DateToStartFrom;
int n = numberOfDays;
List<DateTime> nextNOpenDays = new List<DateTime>();
while(nextNOpenDays.Count < n)
{
if(openDays.Contains(start.DayOfWeek))
nextNOpenDays.Add(start);
start = start.AddDays(1);
}
You can use a case to make a day earlier in this week look like that day next week. Here's an example to look up the next open day:
select top 1 dateadd(day, day_diff, #dt) as dt
from (
select case
when dayofweek <= datepart(dw, #dt) then dayofweek + 7
else dayofweek
end - datepart(dw, #dt) as day_diff
, *
from dbo.OpeningHours
) sub1
order by
day_diff
You can then recurse to find more than one day. If we store the above snippet in a function called get_next_open_day, the recursive common table expression could look like:
; with cte as
(
select dbo.get_next_open_day(#dt) as open_day
, 1 as day_number
union all
select dbo.get_next_open_day(prev_day.open_day)
, prev_day.day_number + 1
from cte as prev_day
where prev_day.day_number < #number_of_days
)
select cte.open_day
, datename(dw, cte.open_day)
from cte
option (maxrecursion 100)
;
Here's a full working example:
use Test
if object_id('OpeningHours') is not null
drop table OpeningHours;
if object_id('dbo.get_next_open_day') is not null
drop function dbo.get_next_open_day;
create table OpeningHours (dayofweek int, opentime time, closetime time);
insert dbo.OpeningHours values
(2, '9:00', '17:00'),
(3, '9:00', '17:00'),
(4, '9:00', '17:00'),
(5, '9:00', '17:00'),
(6, '9:00', '21:00'),
(7, '10:00', '17:00')
;
go
create function dbo.get_next_open_day(
#dt date)
returns date
as begin return
(
select top 1 dateadd(day, day_diff, #dt) as dt
from (
select case
when dayofweek <= datepart(dw, #dt) then dayofweek + 7
else dayofweek
end - datepart(dw, #dt) as day_diff
, *
from dbo.OpeningHours
) sub1
order by
day_diff
)
end
go
--declare #dt date = '2015-02-18' -- Wed
--declare #dt date = '2015-02-20' -- Fri
declare #dt date = '2015-02-22' -- Sun
declare #number_of_days int = 10
; with cte as
(
select dbo.get_next_open_day(#dt) as open_day
, 1 as day_number
union all
select dbo.get_next_open_day(prev_day.open_day)
, prev_day.day_number + 1
from cte as prev_day
where prev_day.day_number < #number_of_days
)
select cte.open_day
, datename(dw, cte.open_day)
from cte
option (maxrecursion 100)
;
The implementation of multiple shops is left as an exercise for the reader.
Try this:
DECLARE #t TABLE(WeekID INT, OpenTime time)
DECLARE #c INT = 10
INSERT INTO #t VALUES
(1, '10:00'),--sunday
(2, '10:00'),--monday
(4, '10:00'),--wednsday
(5, '10:00')--thursday
;WITH Tally (n) AS
(
-- 1000 rows
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(n)
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n)
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(n)
)
SELECT TOP (#c) DATEADD(dd, t.n, GETDATE())
FROM Tally t
JOIN #t s ON DATEPART(w, DATEADD(dd, t.n, GETDATE())) = s.WeekID
Output:
Date
2015-02-22 --sunday
2015-02-23 --monday
2015-02-25 --wednsday
2015-02-26 --thursday
2015-03-01 --sunday
2015-03-02 --monday
2015-03-04 --wednsday
2015-03-05 --thursday
2015-03-08 --sunday
2015-03-09 --monday
PS: You can replace GETDATE() with any date to look from.
I managed to find a solution:
public List<DateTime> getDaysOpen(int numberOfDays, DateTime start)
{
List<byte> openDays = this.getOpeningHoursDays();
List<DateTime> nextNOpenDays = new List<DateTime>();
while (nextNOpenDays.Count < numberOfDays)
{
if (openDays.Contains(Convert.ToByte(start.DayOfWeek)))
nextNOpenDays.Add(start);
start = start.AddDays(1);
}
return nextNOpenDays;
}
public List<byte> getOpeningHoursDays()
{
return db.OpeningHours.Where(oh => oh.LocationId == this.Id).Select(oh => oh.DateOfWeek).ToList();
}
This was in my opinion the easiest method to find a solution. Thank you for all your help.

How to get monthly report from two different month?

I have a table named Leave it contains 2 rows
no=1 Leave=CL,Lnumber=2,FromDate='2015-01-10',ToDate=2015-01-11'
no=2 Leave=CL,Lnumber=2,FromDate='2015-01-12',ToDate=2015-01-13'
no=3 Leave=CL,Lnumber=2,FromDate='2015-01-15',ToDate='2015-02-16'
no=4 Leave=CL,Lnumber=2,FromDate='2015-01-31',ToDate='2015-02-01'
Here I want to get january month leave report(leave and Lnumer). How can I fetch this considering this FromDate and ToDate
The answer should be like this
Leave=CL,Lnumber=7 (for jan month)
Leave=Cl,Lnumber=1 (for feb month)
I am using MSSQL 2008. You can add extra fields if it is necessory. Thank You
I'd recommend building a calendar table (basically a tally table, but with dates). Then join your leave table to the calendar table between the from and to dates, and count the days that fall in the interval.
;with t as
(
select no=1, Leave='CL',Lnumber=2,FromDate=cast('2015-01-10' as date),ToDate=cast('2015-01-11' as date) union all
select no=2, Leave='CL',Lnumber=2,FromDate=cast('2015-01-31' as date),ToDate=cast('2015-02-01' as date)
), cal as
(
select top 10000 _date = cast(cast(row_number() over (order by (select null)) + 41000 as datetime) as date)
from sys.objects a, sys.objects b
)
select
t.Leave,
_year = datepart(year, c._date),
_month = datepart(month, c._date),
count(_date)
from t
inner join cal c
on c._date between t.FromDate and t.ToDate
group by t.Leave, datepart(year, c._date), datepart(month, c._date)

How do I find week number of a date according to DATEFIRST

How to find week number of a date if start day is Tuesday and end day is Monday?
Here is the example criteria
Date Output
...... ..........
01-Dec-2014 (Monday) - 2014_DECEMBER_WEEK_NO_1
04-Dec-2014 (Thursday) - 2014_DECEMBER_WEEK_NO_1
29-Dec-2014 (Monday) - 2014_DECEMBER_WEEK_NO_4
30-Dec-2014 (Tuesday) - 2014_DECEMBER_WEEK_NO_5
31-Dec-2014 (Tuesday) - 2014_DECEMBER_WEEK_NO_5
I tried following query:
select CAST(UPPER(DATENAME(YEAR, #FROMDATE)) AS VARCHAR(20))
+'_'+CAST(UPPER(DATENAME(MONTH, #FROMDATE)) AS VARCHAR(20))
+'_WEEK_NO_'+CAST((DAY(#FROMDATE)
+ (DATEPART(DW, DATEADD (MONTH, DATEDIFF (MONTH, 0, #FROMDATE), 0))-1) -1)/7 + 1 AS VARCHAR(10))
This working fine if start day is Sunday and end day is Saturday.
Set your first day to Tuesday
SET DATEFIRST 2
Execute the following query
DECLARE #FROMDATE DATE='31-Dec-2014'
SELECT CAST(UPPER(DATENAME(YEAR, #FROMDATE)) AS VARCHAR(20))
+'_'+CAST(UPPER(DATENAME(MONTH, #FROMDATE)) AS VARCHAR(20))
+'_WEEK_NO_'+REPLACE(CAST((DAY(#FROMDATE)
+ (DATEPART(DW, DATEADD (MONTH, DATEDIFF (MONTH, 0, #FROMDATE), 0))-1) -1)/7 AS VARCHAR(10)),'0','1')
UPDATE
SET DATEFIRST 2
DECLARE #FROMDATE DATE='12-JAN-2015'
DECLARE #ALLDATE DATE=DATEADD(month, DATEDIFF(month, 0, #FROMDATE), 0)
DECLARE #FIRSTDATE DATE
; WITH CTE as
(
SELECT 1 RNO,CAST(#ALLDATE AS DATE) as DATES
UNION ALL
SELECT RNO+1, DATEADD(DAY,1,DATES )
FROM CTE
WHERE DATES < DATEADD(MONTH,1,#ALLDATE)
)
SELECT TOP 1 #FIRSTDATE = DATES
FROM CTE
WHERE DATEPART(W,DATES)=1
SELECT CAST(UPPER(DATENAME(YEAR, #FROMDATE)) AS VARCHAR(20))
+'_'+CAST(UPPER(DATENAME(MONTH, #FROMDATE)) AS VARCHAR(20))
+'_WEEK_NO_'+CAST((DATEDIFF(DAY,#FIRSTDATE,#FROMDATE)/7)+1 AS VARCHAR(10))
set datefirst 2
DECLARE #StartDate DATE = '2014-12-01',
#EndDate DATE = '2014-12-31',
#DayCount int
SELECT #DayCount = count(* )
FROM (SELECT TOP ( datediff(DAY,#StartDate,#EndDate) + 1 )
[Date] = dateadd(DAY,ROW_NUMBER()
OVER(ORDER BY c1.name),
DATEADD(DD,-1,#StartDate))
FROM [master].[dbo].[spt_values] c1 ) x
WHERE datepart(dw,[Date]) = 1;
select CAST(UPPER(DATENAME(YEAR, #EndDate)) AS VARCHAR(20))
+'_'+CAST(UPPER(DATENAME(MONTH, #EndDate)) AS VARCHAR(20))
+'_WEEK_NO_'+ Cast(#DayCount as varchar)

Find Difference between end dates by comparing rows

i have a table
----------
User
----------
userID(pk)
startdate // update : i am not using this field.
enddate
i need to compare between the end_dates between the rows comparing whether it is more than 3 days and count the userid.
i am doing something similar to this
WHILE ##FETCH_STATUS = 0
BEGIN
select #lastrowID = max(rowid) from #User
if (#userid = (select userId from #User where rowid = #lastRowID))
begin
update #User set NextEndDate= #endDate where rowid = #lastRowID and userid = #userid
end
else
begin
insert #UserTable (userid, EndDate,NextEndDate) values (#userid, #endDate,#NextEndDate)
end
END
my idea is to loop around the table and create a nextend date and then find the comparing using datediff. i am stuck with the first part of creating nextend date and i believe the 2nd part of comparing would be easy. i am stuck in between.
my question is am i doing the right thing, its getting pretty complicated.
i am confused whether to get the result through sql query or use C# at code behind using Linq or something similar.
Update:
sorry If i wasn't clear in explaining my scenario : i am trying to find the count, no of times a client has visited.
ex:
userid: 1 have may a visited daily or once in a month. so i need to get the count(frequency of the user visit). so if the users visited end date was
userid enddate
1 1/1/2010
1 1/2/2010 count 1
1 1/10/2010 count 2 difference is more than 3 days
1 1/13/2010 count 2 ( because diff is less than 3 days)
thats how i should count, thats y i was trying to use cursor which was too complicate for me to solve. I appreciate for your guidance.
Ok, I understand your problem now. I know there is a better way to do this in SQL, maybe with CTEs, but this solution should work and doesn't use cursors. This will give you a full table with the datediff of the previous enddate (where applicable). You can then select from it based on the datediff.
select u1.*, datediff(day, u2.enddate, u1.enddate) as days from
(
select userid, enddate, row_number() over(partition by userid order by userid, enddate) as rownumber
from [user]
) u1
left join
(
select userid, enddate, row_number() over(partition by userid order by userid, enddate) as rownumber
from [user]
)u2
on u1.userid = u2.userid
and u1.rownumber = u2.rownumber + 1
EDIT
declare #table table (userid int, startdate datetime, enddate datetime)
insert into #table (userid, startdate, enddate) values (1, '01-JAN-2010', '2-JAN-2010')
insert into #table (userid, startdate, enddate) values (2, '01-JAN-2010', '3-JAN-2010')
insert into #table (userid, startdate, enddate) values (3, '01-JAN-2010', '4-JAN-2010')
insert into #table (userid, startdate, enddate) values (4, '01-JAN-2010', '5-JAN-2010')
insert into #table (userid, startdate, enddate) values (5, '01-JAN-2010', '6-JAN-2010')
insert into #table (userid, startdate, enddate) values (6, '01-JAN-2010', '7-JAN-2010')
insert into #table (userid, startdate, enddate) values (7, '01-JAN-2010', '8-JAN-2010')
select SUM(yn) as dueinmorethanthreedays from
(select
(case when DATEADD(day,3,startdate) < enddate then 1 else 0 end) as yn
from #table
) as derived
A subquery which returns 1 for each row where the startdate is less than three days of the enddate (and 0 otherwise) can be summed to get the total.

Categories

Resources