Crystal report c# - c#

what I want to do is insert data in crystal report, the challenge is on how can I achieve that.
my data is
Jan 1, Number, Name
Jan 2, Number, Name
Jan 4, Number, Name
Jan 5, Number, Name
Jan 7, Number, Name
what I want to do is regardless of my data, I want to display in my crystal report the whole month.
so the expected output is
Jan 1, Number, Name
Jan 2, Number, Name
Jan 2, Null, Null
Jan 4, Number, Name
Jan 5, Number, Name
Jan 2, Null, Null
Jan 7, Number, Name
Jan 8, Null , Null
...
Jan 31, Null , Null
,is it possible to do this on crystal report?
I can generate it using select * from my queries, but i dont know how to fill in the missing values.

I think you need to create a date table once for the dates you need, then you can join to your data.
Ex. select * from [DateTable] left outer join [your queries] on [DateTable].date=[your queries].date
Here is an example how to create date table once for 10 years period starting from the current year:
DECLARE #StartDate date = '20210101';
DECLARE #CutoffDate date = DATEADD(DAY, -1, DATEADD(YEAR, 10, #StartDate));
;WITH seq(n) AS
(
SELECT 0 UNION ALL SELECT n + 1 FROM seq
WHERE n < DATEDIFF(DAY, #StartDate, #CutoffDate)
),
d(d) AS
(
SELECT DATEADD(DAY, n, #StartDate) FROM seq
),
src AS
(
SELECT
TheDate = CONVERT(date, d),
TheDay = DATEPART(DAY, d),
TheDayName = DATENAME(WEEKDAY, d),
TheWeek = DATEPART(WEEK, d),
TheISOWeek = DATEPART(ISO_WEEK, d),
TheDayOfWeek = DATEPART(WEEKDAY, d),
TheMonth = DATEPART(MONTH, d),
TheMonthName = DATENAME(MONTH, d),
TheQuarter = DATEPART(Quarter, d),
TheYear = DATEPART(YEAR, d),
TheFirstOfMonth = DATEFROMPARTS(YEAR(d), MONTH(d), 1),
TheLastOfYear = DATEFROMPARTS(YEAR(d), 12, 31),
TheDayOfYear = DATEPART(DAYOFYEAR, d)
FROM d
)
SELECT * into dbo.DateTable
FROM src
ORDER BY TheDate
OPTION (MAXRECURSION 0);

Related

matrix report for leaves

I have no.of days, start date and end date stored in table to store no.of leaves of employees.
I want to create report in which user select start date and end date from calendar and report shows the data depending on date selected. But my problem is if the user select a date which is in between start date and end date, I want accurate no.of days for that particular employee.
for ex. the following data saved in database
no of days 3
start date 02/06/2016
end date 04/06/2016
user selected start date 03/06/2016 and end date 04/06/2016 from calendar.
The expected result is: no. of days 2
Please suggest a sql query or C# code
table structure
leaveId empid leavetypeId noofdays startdate enddate
1 76 1 3 2016-06-02 2016-06-04
query i fired like as follows
select noofdays
from table
where startdate='2016-06-03' and enddate='2016-06-04'
and expected result
noofdays = 2
Try following solution:
DECLARE
#pStartDate DATE = {d '2016-06-01'}, -- p = parameter
#pEndDate DATE = {d '2016-06-12'}
SELECT SUM(DATEDIFF(DAY, x.CommonRangeStartDate, x.CommonRangeEndDate) + 1) AS NumOfCommonDays
FROM (VALUES
(1, {d '2016-06-02'}, {d '2016-06-04'}),
(2, {d '2016-06-02'}, {d '2016-06-02'}),
(3, {d '2016-06-04'}, {d '2016-06-10'}),
(4, {d '2016-06-12'}, {d '2016-06-15'}),
(5, {d '2016-06-14'}, {d '2016-06-17'}),
(6, {d '2016-05-01'}, {d '2016-06-18'})
) s(LeaveID, StartDate, EndDate) -- I assume SD & ED's data type is DATE
CROSS APPLY (
SELECT
CASE WHEN s.StartDate >= #pStartDate THEN s.StartDate ELSE #pStartDate END AS CommonRangeStartDate, -- MAX
CASE WHEN s.EndDate <= #pEndDate THEN s.EndDate ELSE #pEndDate END AS CommonRangeEndDate -- MIN
) x
WHERE s.StartDate <= #pEndDate
AND #pStartDate <= s.EndDate
Note #1: Assumptions: StartDate <= EndDate, #pStartDate <= #EndDate
Note #2: If you want to see details then use SELECT * instead of SELECT SUM

Select the first and the last day of a month in sql server for a month already stored in SQL Database

I have a small idea for that but i don't know how to interpret it in sql server (MSDN).
if (Month < ActualMonth)
{
(StartDateReq = FirstDayMonth);
(EndDatereq) = LastDayMonth);
}
else if (Month = currenTimeStamp)
{
(EndDateReq = currentTimeStamp);
}
If you have a date in SQL Server, you can get the first and last day of the month using:
select dateadd(day, 1 - day(datecol), datecol) as firstday,
dateadd(day, -1, dateadd(month, 1, dateadd(day, 1 - day(datecol), datecol))) as lasstday
In SQL Server 2012+, you can use the function EOMONTH() for the last day of the month.
Drawing on Gordon's answer:
DECLARE #myDate Date = '2015-10-25'
select DATEADD(DAY, 1 - DAY(#myDate), #myDate) as firstday,
CASE WHEN YEAR(#myDate) = YEAR(GETDATE()) AND
MONTH(#MyDate) = MONTH(GETDATE())
THEN #MyDate
ELSE DATEADD(DAY, -1, DATEADD(MONTH, 1, DATEADD(DAY, 1 - DAY(#myDate), #myDate)))
END as lasstday

Days in every month with two dates

I am working in HRMS. My problem is in vacation,
If an employee take vacation from 19/3/2014 to 5/4/2014 application calculates that he take 18 days in month instead of 3 days.
I store vacations in vacation table
columns :
emp_id | vac_type | from | to
Now, How can I make query to tell me that he take 13 days in March and 5 days in April?
Excellent question! I was able to find a way to do it, but I did have to use slightly different notation for the dates (see below).
DECLARE #startDate DATETIME, #endDate DATETIME, #lastDayOfStartMonth INT
SET #startDate = '3/19/2014'
SET #endDate = '4/5/2014'
SELECT #lastDayOfStartMonth =
1+DATEPART(dd, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#startDate)+1,0)))
SELECT DATENAME(month, #startDate) AS [Month],
#lastDayOfStartMonth - DATEPART(dd, #startDate) AS [DaysSpent],
DATENAME(month, #endDate) AS [Month],
DATEPART(dd, #endDate) AS [DaysSpent]
Output:
| Month | DaysSpent | Month | DaysSpent |
|-------|-----------|-------|-----------|
| March | 13 | April | 5 |
SQL Fiddle example
My work here was based on the design from Pinal Dave's post SQL SERVER – Find Last Day of Any Month – Current Previous Next
Handling dates over more than two months
DECLARE #startDate DATETIME, #endDate DATETIME, #currentDate DATETIME, #currentDay INT
DECLARE #currentMonth INT, #lastDayOfStartMonth INT
CREATE TABLE #VacationDays ([Month] VARCHAR(10), [DaysSpent] INT)
SET #startDate = '1/19/2014'
SET #endDate = '4/5/2014'
SET #currentMonth = DATEPART(mm, #startDate)
SET #currentDay = DATEPART(dd, #startDate)
SET #currentDate = #startDate
WHILE #currentMonth < DATEPART(mm, #endDate)
BEGIN
SELECT #lastDayOfStartMonth =
DATEPART(dd, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#currentDate)+1,0)))
PRINT #lastDayOfStartMonth
INSERT INTO #VacationDays
SELECT DATENAME(month, #currentDate) AS [Month],
#lastDayOfStartMonth - #currentDay + 1 AS [DaysSpent]
SET #currentDate = DATEADD(mm, 1, #currentDate)
SET #currentMonth = #currentMonth + 1
SET #currentDay = 1
END
IF DATEPART(mm, #startDate) = DATEPART(mm, #endDate)
BEGIN
INSERT INTO #VacationDays
SELECT DATENAME(month, #endDate) AS [Month],
DATEPART(dd, #endDate) - DATEPART(dd, #startDate) + 1 AS [DaysSpent]
END
ELSE
BEGIN
INSERT INTO #VacationDays
SELECT DATENAME(month, #endDate) AS [Month],
DATEPART(dd, #endDate) AS [DaysSpent]
END
SELECT * FROM #VacationDays
DROP TABLE #VacationDays
Output:
| Month | DaysSpent |
|----------|-----------|
| January | 13 |
| February | 28 |
| March | 31 |
| April | 5 |
SQL Fiddle example - It takes about a minute to run. It's much faster running in a local instance of SSMS.
Here's how it works
For the example below I am using a #startDate value of 05-05-2015.
The value of CAST(0 AS DATETIME) is the date 1900-01-01, so that means the line DATEDIFF(m,0,#startDate) is essentially asking, how many months have passed since January 1, 1900? For this example, that value is 1384.
DATEADD(mm, DATEDIFF(m,0,#startDate)+1,0) or DATEADD(mm, 1384+1,0) is saying, Add 1385 months to the date value 0 (or 1900-01-01). This will give us the DATETIME value of the first of the month after #startDate's month. For our example, 2015-06-01.
DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#startDate)+1,0)) or DATEADD(s,-1,'2015-06-01') subtracts 1 second from the first of next month, give us the last second of the current month, or 2015-05-31 23:59:59.
Then we use DATEPART to get the day value of that date: 31.
31 is the last day in May.
I don't know how to do this directly in SQL using a SQL query. But if you have the start and end dates of the vacation in your C# code, then you could calculate the number of days of vacation occurring in each month by doing something like the following. This got a little more complicated than I had intended, but it's the best I could come up with. For your example, this code produces the following output:
Vacation days in March: 13 days
Vacation days in April: 5 days
Code:
class Program
{
class DateRange
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
}
static void Main(string[] args)
{
DateRange vacation = new DateRange();
vacation.Start = new DateTime(2014, 3, 19);
vacation.End = new DateTime(2014, 4, 5);
// Assuming April 5 represents the last day of vacation, let's
// add one to it, to show that his vacation actually ends on the
// following day.
vacation.End = vacation.End.AddDays(1);
DateRange currentMonth = new DateRange();
currentMonth.Start = new DateTime(vacation.Start.Year, vacation.Start.Month, 1);
currentMonth.End = currentMonth.Start.AddMonths(1);
while (currentMonth.Start < vacation.End)
{
Console.WriteLine("Vacation days in {0}: \t{1} days",
currentMonth.Start.ToString("MMMM"),
IntersectDates(currentMonth, vacation));
currentMonth.Start = currentMonth.Start.AddMonths(1);
currentMonth.End = currentMonth.End.AddMonths(1);
}
}
// Returns the number of days represented by the intersection of the two
// date ranges.
static int IntersectDates(DateRange dateRange1, DateRange dateRange2)
{
DateTime startOfIntersection = MaxDate(dateRange1.Start, dateRange2.Start);
DateTime endOfIntersection = MinDate(dateRange1.End, dateRange2.End);
return (startOfIntersection < endOfIntersection) ?
(int)(endOfIntersection - startOfIntersection).TotalDays :
0;
}
static DateTime MinDate(DateTime d1, DateTime d2)
{
return (d1 < d2) ? d1 : d2;
}
static DateTime MaxDate(DateTime d1, DateTime d2)
{
return (d1 > d2) ? d1 : d2;
}
}
DECLARE #FromDate date = '2014-03-19', #ToDate date = '2014-05-04'
WITH CTE AS
(
SELECT
YEAR(#FromDate) * 100 + MONTH(#FromDate) AS Month,
DATEADD(DAY, -DAY(#FromDate) + 1, #FromDate) AS FirstDateOfMonth,
DATEADD(DAY, -1, DATEADD(MONTH, 1, DATEADD(DAY, -DAY(#FromDate) + 1, #FromDate))) AS LastDateOfMonth
UNION ALL
SELECT
YEAR(DATEADD(MONTH, 1, FirstDateOfMonth)) * 100 + MONTH(DATEADD(MONTH, 1, FirstDateOfMonth)) AS Month,
DATEADD(MONTH, 1, FirstDateOfMonth),
DATEADD(DAY, -1, DATEADD(MONTH, 2, FirstDateOfMonth))
FROM CTE
WHERE #ToDate >= LastDateOfMonth
)
SELECT
*,
CASE
-- Same month
WHEN YEAR(#FromDate) * 100 + MONTH(#FromDate) = YEAR(#ToDate) * 100 + MONTH(#ToDate) THEN DATEDIFF(DAY, #FromDate, #ToDate) + 1
-- Get day from vacation start date to last date of month
WHEN Month = YEAR(#FromDate) * 100 + MONTH(#FromDate) THEN DATEDIFF(DAY, #FromDate, LastDateOfMonth) + 1
-- Get day from first date of month to vacation end date
WHEN Month = YEAR(#ToDate) * 100 + MONTH(#ToDate) THEN DATEDIFF(DAY, FirstDateOfMonth, #ToDate) + 1
-- Full month day
ELSE DATEDIFF(DAY, FirstDateOfMonth, LastDateOfMonth) + 1
END AS Day
FROM CTE
Result
Month FirstDateOfMonth LastDateOfMonth Day
----------- ---------------- --------------- -----------
201403 2014-03-01 2014-03-31 13
201404 2014-04-01 2014-04-30 30
201405 2014-05-01 2014-05-31 4
For applications like these, a dates table can greatly simplify queries at a reasonable cost to performance. It becomes nothing more than
SELECT emp_id, d.month, COUNT(*) as days
FROM Vacations v
INNER JOIN dates d on d.theDate BETWEEN v.Start and v.End
GROUP BY emp_id, d.month
See Create Date Dimension Table in SQL Server for an example of how to create a dates table.
This also simplifies complicated queries like the number of business days in a vacation:
SELECT emp_id, COUNT(*) as days
FROM Vacations v
INNER JOIN dates d on d.theDate BETWEEN v.Start and v.End
WHERE d.IsWeekend = 0
GROUP BY emp_id
Or grouping by pay-period or quarter:
SELECT emp_id, d.year, d.quarter, COUNT(*) as days
FROM Vacations v
INNER JOIN dates d on d.theDate BETWEEN v.Start and v.End
GROUP BY emp_id, d.year, d.quarter
I create a query that needs a calendar that I make it in WITH statement, In this calendar you can set your month names and month days -for a leap year-.
The calendar will be flexible for any year that used in vacation table -that automatically generate the correct dates for leap years-, Also support vacations starts from one year to next year.
;WITH calendar AS (
SELECT years.[Year], months.monthId, months.[monthName],
CASE ISDATE(CONVERT(varchar, years.[Year])+'-'+CONVERT(varchar,months.monthId)+'-'+CONVERT(varchar,months.monthDays))
WHEN 1 THEN months.monthDays
ELSE months.monthDays-1
END AS monthDays,
CONVERT(datetime, (CONVERT(varchar, years.[Year])+'-'+CONVERT(varchar,months.monthId)+'-1')) AS startDay,
CASE ISDATE(CONVERT(varchar, years.[Year])+'-'+CONVERT(varchar,months.monthId)+'-'+CONVERT(varchar,months.monthDays))
WHEN 1 THEN CONVERT(datetime, CONVERT(varchar, years.[Year])+'-'+CONVERT(varchar,months.monthId)+'-'+CONVERT(varchar,months.monthDays))
ELSE CONVERT(datetime, CONVERT(varchar, years.[Year])+'-'+CONVERT(varchar,months.monthId)+'-'+CONVERT(varchar,months.monthDays-1))
END AS EndDay
FROM
(SELECT DISTINCT YEAR(vi.[from]) As [Year] FROM vacation vi
UNION
SELECT DISTINCT YEAR(vi.[to]) As [Year] FROM vacation vi
) As years
CROSS JOIN
(SELECT 1 As monthId, 31 As monthDays, 'January' As [monthName] UNION ALL
SELECT 2, 29, 'February' UNION ALL
SELECT 3, 31, 'March' UNION ALL
SELECT 4, 30, 'April' UNION ALL
SELECT 5, 31, 'May' UNION ALL
SELECT 6, 30, 'June' UNION ALL
SELECT 7, 31, 'July' UNION ALL
SELECT 8, 31, 'August' UNION ALL
SELECT 9, 30, 'September' UNION ALL
SELECT 10, 31, 'October' UNION ALL
SELECT 11, 30, 'November' UNION ALL
SELECT 12, 31, 'December' ) As months
)
SELECT c.[year], c.monthId, c.[monthName],
CASE
WHEN v.emp_id IS NULL THEN 0
WHEN c.monthId = MONTH(v.[from]) THEN DATEDIFF(DAY, v.[from], c.EndDay) + 1
WHEN c.monthId = MONTH(v.[to]) THEN DATEDIFF(DAY, c.startDay, v.[to]) + 1
WHEN c.monthId BETWEEN MONTH(v.[from]) AND MONTH(v.[to]) THEN c.monthDays
END As vacationDays,
CASE
WHEN v.emp_id IS NULL THEN c.monthDays
WHEN c.monthId = MONTH(v.[from]) THEN DATEDIFF(DAY, c.startDay, v.[from])
WHEN c.monthId = MONTH(v.[to]) THEN DATEDIFF(DAY, v.[to], c.EndDay)
WHEN c.monthId BETWEEN MONTH(v.[from]) AND MONTH(v.[to]) THEN 0
END As nonvacationDays,
c.monthDays
FROM
calendar c
LEFT JOIN
vacation v ON c.monthId BETWEEN MONTH(v.[from]) AND MONTH(v.[to])
The result will be like this:
year | monthId | monthName | vacationDays | nonvacationDays | monthDays
-----+---------+-----------+--------------+-----------------+------------
2014 | 1 | January | 0 | 31 | 31
2014 | 2 | February | 0 | 28 | 28
2014 | 3 | March | 13 | 18 | 31
2014 | 4 | April | 5 | 25 | 30
2014 | 5 | May | 0 | 31 | 31
--....

Getting records with month by month, year by year and day by day from SQL Server

I'm looking for a fast and easy SQL Query to get records year by year, month by month and day by day.
My database example:
ID - DATE - CatID - VALUE
1 - 2013-08-06 - 32 - 243
2 - 2013-08-16 - 2 - 45
3 - 2013-08-21 - 2 - 1
4 - 2013-08-05 - 32 - 450
5 - 2013-08-05 - 32 - 449
6 - 2013-08-05 - 32 - 11
7 - 2013-08-01 - 2 - 221
8 - 2013-08-02 - 32 - 0
9 - 2013-08-02 - 32 - 0
10 - 2013-08-02 - 32 - 987
...
..
I have over 2 millions records on this table.
First:
I would like to get CatID = 32 and single/higher record of the day.
Result:
1 - 2013-08-06 - 32 - 243
4 - 2013-08-05 - 32 - 450
10 - 2013-08-02 - 32 - 987
Second:
I would like to get as same but by MONTH.
How can I do it with SQL SERVER. Currently Sql Server 2012.
Also using C# 5 and if you want to use, EF 6.
Down voters, this question became "popular question". Now please explain why down voted?
The below assumes that you want more than just the max value for each date/month, but also want to know the id of that row, etc, etc.
For daily...
WITH
sorted AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY CatID,
Date
ORDER BY Value DESC) AS ordinal_cat_date
FROM
yourTable
)
SELECT
*
FROM
sorted
WHERE
ordinal_cat_date = 1
AND catID = 32
For monthly...
WITH
sorted AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY CatID,
DATEADD(MONTH, DATEDIFF(MONTH, 0, Date), 0)
ORDER BY Value DESC) AS ordinal_cat_month
FROM
yourTable
)
SELECT
*
FROM
sorted
WHERE
ordinal_cat_month = 1
AND catID = 32
In both cases the ROW_NUMBER() function creates a sequence of numbers (1,2,3,4,etc) for each PARTITION of catID, date, in descending order of value. Whichever row has a value of 1 is the row with the highest value in that partition.
The formula DATEADD(MONTH, DATEDIFF(MONTH, 0, Date), 0) just rounds the Date down to the first day of the month, thereby creating partitions for whole months.
Some other options that bring through multiple rows per day/month if those rows all share the same highest value...
SELECT -- Daily Version
*
FROM
yourTable
WHERE
NOT EXISTS (SELECT *
FROM yourTable AS lookup
WHERE lookup.CatID = yourTable.CatID
AND lookup.Value > yourTable.Value
AND lookup.Date = yourTable.Date
)
AND CatID = 32
SELECT -- Monthly Version
*
FROM
yourTable
WHERE
NOT EXISTS (SELECT *
FROM yourTable AS lookup
WHERE lookup.CatID = yourTable.CatID
AND lookup.Value > yourTable.Value
AND lookup.Date >= DATEADD(MONTH, DATEDIFF(MONTH, 0, yourTable.Date), 0)
AND lookup.Date < DATEADD(MONTH, 1+DATEDIFF(MONTH, 0, yourTable.Date), 0)
)
AND CatID = 32
Or possibly...
SELECT -- Daily Version
*
FROM
yourTable
INNER JOIN
(
SELECT
Date,
CatID,
MAX(Value) AS max_value
FROM
yourTable
GROUP BY
CatID,
Date
)
AS lookup
ON yourTable.Date = lookup.Date
AND yourTable.CatID = lookup.CatID
AND yourTable.Value = lookup.max_value
WHERE
yourTable.CatID = 32
SELECT -- Monthly Version
*
FROM
yourTable
INNER JOIN
(
SELECT
CatID,
DATEADD(MONTH, DATEDIFF(MONTH, 0, yourTable.Date), 0) AS month_start,
MAX(Value) AS max_value
FROM
yourTable
GROUP BY
CatID,
DATEADD(MONTH, DATEDIFF(MONTH, 0, yourTable.Date), 0)
)
AS lookup
ON yourTable.Date >= lookup.month_start
AND yourTable.Date < DATEADD(MONTH, 1, lookup.month_start)
AND yourTable.CatID = lookup.CatID
AND yourTable.Value = lookup.max_value
WHERE
yourTable.CatID = 32

Month/Year SQL to correct format

I have a textfield that users input the date using a modified jquery datepicker. The textfield has the Month and Year such as 'July 2011'
I need to run a query to search for results between July 1, 2011 and July 31, 2011. My date in the database is a smalldatetime, so I need my query to look like this:
select * from members where signupdate between 'july 1 2011' and 'july 31 2011'
How can I get the user inputted date of July 2011 converted to 'July 1 2011' and 'July 31 2011'?
EDIT
I'm only getting a 0 value from InvalidCount but I know I have one record in there as a test. Why isn't it being counted?
MY PROC:
SELECT
(SELECT COUNT(*) FROM dbo.Members m WHERE m.memberID = #pMemberID AND m.SignUpDate BETWEEN #pDate AND DATEADD(MONTH, 1, #pDate)-1) AS 'SignUpDate',
COALESCE(SUM(m.ValidCount), 0) AS ValidCount,
COALESCE(SUM(m.InvalidCount), 0) AS InvalidCount
FROM
dbo.Members m
INNER JOIN
dbo.MemberStats ms ON m.MemberID = ms.MemberID
WHERE
m.SignUpdate BETWEEN #pDate AND DATEADD(MONTH, 1, #pDate)-1
The exact syntax depends on the SQL Engine, but if you start with the 1st of the month, then add 1 month, and finally subtract 1 day; you get the end of the month.
(I'll assume MS SQL Server to match your C# tag)
SELECT
*
FROM
members
WHERE
signupdate BETWEEN #param AND DATEADD(MONTH, 1, #param) - 1
If the between isn't required, you can use DatePart.
Untested example:
where DATEPART(yyyy, SignupDate) = 2011 and DATEPART(m, SignupDate) = 7
convert varchar to appropiate format you want and then compare
check the list of formats. Hope this helps dude.
convert date
Firstly, you must convert the string representation to a valid DateTime struct object on the server. You can use var date = DateTime.ParseExact("july 1 2011", "MMMM dd yyyy", CultureInfo.CurrentUICulture) or DateTime.TryParse. Then you pass this into your SqlCommand as parameters. Never use strings when querying, especially when it comes from user input.

Categories

Resources