Get total in HH:MM format from the dataset - c#

CREATE procedure St_Proc_GetUserReportforCurrentDayTask
#userID int
as
Begin
set NoCount on;
DECLARE #TODAY DATE
SET #TODAY = CONVERT(VARCHAR(10), GETDATE(), 111)
select CONVERT(VARCHAR,production.CalendarDate,101) + RIGHT (CONVERT(VARCHAR,production.CalendarDate , 100 ) ,7) as Date,
RegionAndProjectInfo.RegionProjectName as Region ,
County.CountyName as County,
WorkType.WorkTypeName as WorkType,
Task.TaskName as Task,
Production.VolumeProcessed as 'Volumes Processed',
Production.TimeSpent as 'Duration'
from Production
inner join RegionAndProjectInfo
on
RegionAndProjectInfo.RegionProjectID=Production.RegionProjectID
inner join County
on
County.CountyID=Production.CountyID
inner join WorkType
on
WorkType.WorkTypeID=Production.WorkTypeID
inner join Task
on
Task.TaskID=Production.TaskID
where Production.UserID=#userID and CalendarDate >= #TODAY
End
From the above Stored Procedure i am filling a Dataset.After that i am binding this Dataset to a grid view.
In the dataset ,the Column Duration contains Data in HH:MM Format(example-01:00,12:45,02:59 etc).Is there a way that i can get the total of Duration in HH:MM format from the dataset itself.I dont want to query again from the Database to get the Sum of the Duration.

If you're using at least SQL-Server 2008, you should use Time datatype to represent a .NET TimeSpan.
To get it to work with a varchar-column, i would use Linq-To-DataSet, for example:
var timeSpans = dataSet.Tables[0].AsEnumerable()
.Select(r => new {
DurHour = r.Field<String>("Duration").Split(':')[0],
DurMinute = r.Field<String>("Duration").Split(':')[1]
})
.Select(x => new TimeSpan(int.Parse(x.DurHour), int.Parse(x.DurMinute), 0));
Console.WriteLine("Total time in minutes: {0}", timeSpans.Sum(ts=>ts.TotalMinutes));
But that is only a workaround, actually you should really avoid to store a timespan in a varchar column, use varchar only for text and nothing else.
In SQL-Server 2005 (or other dbms) you could also use two columns, one for the start DateTime and one for the end DateTime.

Related

How can I get SQL data values according to machine name filtering?

When I tried to get specific data values of machine address I could not get values of this
ALTER PROCEDURE [dbo].[Datade]
#makineadı varchar,
#startdate datetime
AS
BEGIN
SET NOCOUNT ON;
SELECT *
FROM HMI.[dbo].Tarihmakine
WHERE MakineAdı = #makineadı
AND Tarih = #startdate
END
And I used this stored procedure inside of this API controller, normally when I tried to get desired date of the SQL data I can pull it but when I tried to string format of machine name I could not get data of this I think this caused of DOUBLE QUOTE but I could not convert it to single ''
public class RaporController : ApiController
{
public IHttpActionResult Getemprecords(string makineadı, DateTime? startdate)
{
HMIEntities1 sd = new HMIEntities1();
var results = sd.Data(makineadı, startdate).ToList();
return Ok(results);
}
}
I used this web page to get specific values https://localhost:44355/api/rapor?makineadı=192.168.0.8&&startdate=2021-01-29
Here is my database enter image description here
Your code looks like SQL Server. If so, never use string declarations without a length:
ALTER PROCEDURE [dbo].[Datade] (
#makineadı varchar(255),
#startdate datetime
) AS
BEGIN
SET NOCOUNT ON;
select *
from HMI.[dbo].Tarihmakine
where MakineAdı = #makineadı and Tarih = #startdate
END;
The default date also varies by context -- and these bugs can be very hard to debug. In your case, the default is varchar(1), which is not what you intend.
The other potential issue is the use of datetime for the second argument. However, what you want is not clear:
If you. Tarih is a date, then pass the argument in as a date.
If Tarih is a datetime and you want the values on the same date, then pass in a date and use convert(date, Tarih) = #startdate.
Only use the code as is if Tarih is a datetime (of some sort) and you want the comparison down to a fraction of a second.

Wrong date when using SQL Server stored procedure with Dapper

I am using a stored procedure with Dapper to retrieve data from a table. The stored procedure works fine when executed in SQL Server and returns the required information.
But when I use Dapper to run the stored procedure and retrieve a Date, the Date is returned as 01/01/0001.
Here is my stored procedure which works perfectly in SQL Server:
ALTER PROCEDURE [dbo].[spRankings_GetByEventAndGender]
#Event varchar(50),
#Gender varchar(10)
AS
BEGIN
DECLARE #event_factor INT = CASE
WHEN #Event IN ('Javelin', 'Discus', 'Shot Put', 'Hammer', 'Long Jump', 'High Jump', 'Triple Jump', 'Pole Vault')
THEN -1 /* reverse ranking = highest value is best */
ELSE 1 /* normal ranking = lowest value is best */
END;
SELECT
CASE
WHEN a.mark = ABS(b.mark)
THEN CAST(b.rank AS VARCHAR)
ELSE ''
END AS [Rank],
/*
,a.athleteid
,a.teamid
,a.eventid
*/
CASE
WHEN #event_factor = -1
THEN LTRIM(STR(a.mark, 10, 2))
ELSE FORMAT(DATEADD(SECOND, FLOOR(a.mark), 0),case when a.mark<60 then '' else 'm:' end+'ss')
+substring(ltrim((str(cast(a.mark as decimal(12,5))%1,10,2))),2,10)
end as Mark
,a.wind as Wind
,d.eventname as [Event]
,c.firstname+' '+c.lastname as Athlete
--,Convert(varchar(10),c.BirthDate,103) as [Birth Date]
,c.BirthDate as [BirthDate]
,e.teamname as [Team]
,a.venue as Venue
--, Convert(varchar(10),a.PerformanceDate,103) as [Performance Date]
,a.PerformanceDate as [Performance Date]
from dbo.Performances as a
inner join (select a.PersonId
,a.eventid
,min(a.mark*#event_factor) as mark
,rank() over(partition by a.eventid order by min(a.mark*#event_factor)) as [rank]
,avg(a.mark) as avg_mark
from dbo.Performances as a
inner join dbo.Persons as b
on b.PersonId=a.PersonId
inner join dbo.[Events] as c
on c.eventid=a.eventid
inner join dbo.Meets as d
on d.MeetId = a.MeetId
where b.gender=#Gender
and c.eventname=#Event
group by a.PersonId
,a.eventid
) as b
on b.eventid=a.eventid
and b.PersonId=a.PersonId
inner join dbo.Persons as c
on c.PersonId=a.PersonId
inner join dbo.events as d
on d.eventid=a.eventid
inner join dbo.teams as e
on e.teamid=a.teamid
inner join dbo.Meets as m
on m.MeetId = a.MeetId
order by a.eventid
,a.mark*#event_factor
,b.[rank]
/*
,b.avg_mark
,a.athleteid
*/
end
The results in SQL Server:
The method that uses Dapper to get the results:
public List<RankingsModel> GetRankingsByEventAndGender(string eventName, string gender) {
using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(Helper.GetConString("GARanks"))) {
var output = connection.Query<RankingsModel>($"dbo.spRankings_GetByEventAndGender #Event, #Gender", new { Event=eventName, Gender=gender}).ToList();
return output;
}
}
The results in my application:
You are getting the default value in the application. Please find below links which can help:
Date is 01/01/0001 and not the date that is in the database?
DateTime shows the date as 01/01/0001
HTH
Thanks.
You can probably break the problem down into pieces. First make sure that Dapper is returning the right result set. You could
connection.Query<Object>
or
connection.Query<dynamic>
and inspect the result to see if it has the right DateTime value in it, in debug mode. If it does, then the problem isn't dapper retrieving the results from the database, it's that it can't map it to your POCO/class.
If the result dataset doesn't have the right value of Performance Date, then the problem is with the sql generation that Dapper is doing, and you could look into renaming the column to be without spaces, or pursue that avenue.
Good luck!
You probably have a property named 'PerformanceDate' in RankingsModel class which does not get mapped with 'Performance Date' returned from DB call.
Kindly update the SQL to return 'PerformanceDate' or make same name for both.
The other option is using Column Mapping

Displaying Column Headers As Dates Telerik Rad Grid

Normally I would have code to post. However, I'm not sure where to start on this one. Maybe I am incorrect but this request is a little different than most (from clients). So, they are needing a new feature added to their page. They want to be able to run a report which shows all employees total hours for a given set of weeks. They will use a DatePicker to select a start date and another to select and end date. Then, click a button to run the report. This report will have the employee name as the first column and then each column after that will have a header which is a date. So if they selected 8-5-2017 and 8-19-2017 the column headers will be 8-5-2017| 8-12-2017| 8-19-2017. Underneath those columns will be the total hours each employee worked for that given week.
I've attached an image of what I am needing to do. Hopefully this will provide additional clarification.
I've had a similar situation and managed to solve it by using a DataTable that contained my data. A simple way to fill your DataTable would be by creating a stored procedure.
In my example I'll simply do it for every day between 2 given dates, you should be able to change this code to have it work for once every 7 days, starting on a monday/sunday, depending on what your requirement is. If you need help with that as well, just leave a comment and I'll see what I can do if I find some time.
CREATE TYPE [dbo].[DayTableType] AS TABLE(
[Datum] [date] NOT NULL,
[DayCol] [int] NOT NULL
)
GO
CREATE PROCEDURE [dbo].[MyStoredProcedure]
-- Add the parameters for the stored procedure here
#d1 datetime, #d2 datetime
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SET DATEFIRST 1;
-- Insert statements for procedure here
DECLARE #StartDate date = CONVERT(date, #d1);
DECLARE #EndDate date = CONVERT(date, #d2);
DECLARE #Days dbo.DayTableType;
WITH cte AS (
SELECT #StartDate AS Datum
UNION ALL
SELECT DATEADD(day,1,Datum) as Datum
FROM cte
WHERE DATEADD(day,1,Datum) <= #EndDate
)
INSERT INTO #Days
SELECT cte.Datum, DATEPART(DAY, cte.Datum)
FROM cte
OPTION(MAXRECURSION 0);
DECLARE #dPivot NVARCHAR(MAX)
SELECT #dPivot = ''
SELECT #dPivot = #dPivot + '[' + CONVERT(VARCHAR(8),d.Datum,3) + '],' FROM #Days d
SELECT #dPivot = SUBSTRING(#dPivot,1,LEN(#dPivot)-1)
DECLARE #SQLSTR NVARCHAR(MAX);
SET #SQLSTR =
'SELECT p.EmployeeId
,p.LastName
,p.FirstName
,'+ #dPivot + '
FROM (SELECT CONVERT(VARCHAR(8),d.Datum,3) AS DayCol
,e.EmployeeId
,e.LastName
,e.FirstName
,ISNULL((SELECT SUM(w.WorkedHours) FROM dbo.[EmployeeWorkDateTable] w
WHERE w.EmployeeId = e.EmployeeId AND CONVERT(DATE, w.WorkDate) = CONVERT(DATE, d.Datum)),0) AS DayInfo
FROM #Days d
LEFT OUTER JOIN dbo.[EmployeeTable] e ON e.IsActive = 1
) t
PIVOT (
MAX(t.DayInfo)
FOR t.DayCol IN (' + #dPivot + ')
) AS p
ORDER BY p.LastName'
EXECUTE SP_EXECUTESQL #SQLSTR, N'#Days DayTableType READONLY, #StartDate DATE, #EndDate DATE', #Days, #StartDate, #EndDate
END
This should return a DataTable that looks a lot like what you've posted in your screenshot.
To have this display correctly into your GridView you have need to first get this in your ViewModel as followed:
private DataTable _myDataTable;
public DataTable MyDataTable
{
get { return _myDataTable; }
set { SetProperty(ref _myDataTable, value); }
}
public void FillMyDataTable(DateTime startDate, DateTime endDate)
{
using (var conn = new SqlConnection("MyConnectionString"))
using (var cmd = new SqlCommand("MyStoredProcedure", conn) { CommandType = System.Data.CommandType.StoredProcedure })
{
cmd.Parameters.AddWithValue("#d1", startDate);
cmd.Parameters.AddWithValue("#d2", endDate);
var da = new SqlDataAdapter(cmd);
var ds = new DataSet();
da.Fill(ds);
MyDataTable = ds.Tables[0];
}
}
Now you should simply bind your GridView itemsource to the DefaultView property of your DataTable and have the AutoGenerateColumns="True", you can edit the column names and other stuff even more by writing your custom emplementation of AutoGeneratingColumn
<telerik:RadGridView x:Name="MyGridView"
AutoGenerateColumns="True"
ItemsSource="{Binding MyDataTable.DefaultView}"
AutoGeneratingColumn="MyGridView_OnAutoGeneratingColumn">
</telerik:RadGridView>
I hope this helps you out with your problem. Feel free to leave a comment if you have any more questions.

SQL Server: Search values of type "varchar" with parameters of type "date"

I have a column "Uploaded" of type varchar(25). It has datetime values. Since the string stored in this column is not valid date(front-end is passing them. No control over there) it is kept as varchar(25). The strings stored in it are like:
2016:04:14 21:20:35
2016:04:14 21:20:35
2016:04:14 21:20:35
.
.
.
I need to compare these values in a search query
Select * from Table where [Uploaded] BETWEEN #StartDate AND #EndDate
#StartDate and #EndDate are date type variables. Obviously the above query won't work. So, I have 2 ways:
1. Write correct query that can compare the passed date type variables with the "Uploaded" column.
2. Update the [Uploaded] column values and re-store them as a valid datetime type.
How can that be achieved? Can someone help me writing either the correct search query or update all the records to convert them in valid datetime type?
If you got : between year, month and day in [Uploaded] field then use this:
SELECT *
FROM Table
WHERE CAST(REPLACE(LEFT([Uploaded],10),':','-') as date) BETWEEN #StartDate AND #EndDate
If datetime needed then:
SELECT *
FROM Table
WHERE CAST(REPLACE(LEFT([Uploaded],10),':','-') + RIGHT([Uploaded],9) as datetime) BETWEEN #StartDate AND #EndDate
This will give you accurate result.
select * from Table where cast(replace(left([Upholded],10),':','-')+right([Upholded],len([Upholded]-10) as datetime) between #StartDate AND #EndDate
you can cast the string data to a datetime value and then use datetime comparison
Select * from Table where CAST( [Uploaded] as Date) BETWEEN #StartDate AND #EndDate
make sure you use the right format for your datetime conversions and you should be golden.
here's some more info : https://msdn.microsoft.com/en-us/library/ms187819.aspx

What is a good algorithm to manipulate a lot of DateTime Records?

I have a SQL server table in form of
DATA,Startdatetime,Enddatetime
And it means that my sensor has an state of DATA in duration of Startdatetime and Enddatetime. I have lots of these data. So is there any algorithm or class or a way to query (in c# level or SQL level) that I can ask in a specific time what was my sensor state?
In SQL if you want the data for instance for '2015-08-16 17:33:45'
select data
from your_table
where '2015-08-16 17:33:45' between Startdatetime and Enddatetime
Expanding the other answer here with your additional requirement of being able to do this over multiple points in time:
DECLARE #startDate DATETIME2(0) = '2015-01-01',
#endDate DATETIME2(0) = '2016-01-01',
#intervals INT;
SELECT #intervals = 2 * DATEDIFF(MINUTE, #startDate, #endDate) + 1;
WITH pointsInTime AS (
SELECT DATEADD(SECOND, 30*(n-1), #startDate) AS p
FROM dbo.[Numbers] AS [n]
WHERE n < #intervals
)
SELECT p.p, t.DATA
FROM [pointsInTime] AS p
LEFT JOIN dbo.yourTable AS t
ON p.p >= StartDateTime AND p.p <= EndDateTime;
Where dbo.Numbers is a bog standard tally table. The idea here is to generate the 30 second intervals using the tally table and then use that to drive the select of your data. Note - I used a left join because I don't know if there's a guarantee of there being data for a given data point. If you don't need such times to show up in your result set, you can safely change it to an inner join.

Categories

Resources