Adding 0 to a date in sqlite - c#

I am trying to get my values sorted ascending but although I get the results, it is not sorted properly as seen below:
"50","2016-12-1","2016-12-01 17:42:30","2016-12-01 17:42:30","0","0"
"50","2016-12-10","2016-12-10 07:31:43","2016-12-10 07:31:43","0","0"
"50","2016-12-11","2016-12-11 04:27:35","2016-12-11 04:27:35","0","0"
"50","2016-12-12","2016-12-12 07:52:18","2016-12-12 18:02:47","10","10"
"50","2016-12-13","2016-12-13 07:28:22","2016-12-13 18:18:31","10","50"
"50","2016-12-14","2016-12-14 07:32:34","2016-12-14 18:37:09","11","4"
"50","2016-12-15","2016-12-15 07:14:15","2016-12-15 07:14:15","0","0"
"50","2016-12-2","2016-12-02 07:23:33","2016-12-02 17:37:22","10","13"
"50","2016-12-3","2016-12-03 07:49:27","2016-12-03 17:45:01","9","55"
"50","2016-12-5","2016-12-05 07:40:22","2016-12-05 17:32:29","9","52"
"50","2016-12-6","2016-12-06 07:41:43","2016-12-06 17:42:00","10","0"
"50","2016-12-7","2016-12-07 07:20:33","2016-12-07 17:40:51","10","20"
"50","2016-12-8","2016-12-08 07:22:02","2016-12-08 20:56:37","13","34"
"50","2016-12-9","2016-12-09 07:35:06","2016-12-09 18:11:18","10","36"
The 2016-12-2 is below the 2016-12-15. This is how I get this values:
SELECT uid, scan_date as 'Date' , min(scan_time) as 'Time In', max(scan_time) as 'Time
CAST(((strftime('%s', max(scan_time)) - strftime('%s', min(scan_time))) % (60 * 60 * 24)) / (60 * 60) AS TEXT) as Hours,
CAST((((strftime('%s', max(scan_time)) - strftime('%s', min(scan_time))) % (60 * 60 * 24)) % (60 * 60)) / 60 AS TEXT) as Minutes
FROM tbl_scanTimes
GROUP BY uid, scan_date
ORDER BY uid asc, scan_date
This is how I insert data into the sqlite
var sCommand = new StringBuilder(#"REPLACE INTO tbl_scanTimes(branch, uid, scan_date, scan_time) VALUES ");
sCommand.Append(string.Join(",", (from DataRow row in values.Rows
let branch = _yard
let empId = row[0].ToString().Trim()
let scanTime = row[1].ToString().Trim()
let date = Convert.ToDateTime(scanTime)
let oDate = date.Year+"-"+date.Month+"-"+date.Day
select string.Format("('{0}','{1}','{2}','{3}')", branch, empId, oDate, scanTime)).ToArray()));
sCommand.Append(";");
Is there a way that I can put 0 in the day part of 2016-12-1 so that it will be 2016-12-01? Thank you.

Following CL's comment on supported date formats, I think that your data-inserting may be using your desktop dateformat settings, because you are passing oDate as just '{2}' in the format string.
Try using this format when you insert data:
string.Format("('{0}','{1}','{2}','{3}')",
branch, empId, oDate.ToString("yyyy-MM-dd HH:mm:ss.fff"), scanTime)
(yes, I know that it can be packed into {2} expr, I just want it to stand out).
Btw. watch out for the upper-case MM and HH. It's important.
Here's the full list
Whever it works or not, check carefully what's the actual query you are sending to the db. Place a breakpoint on that line and see what the Format() method produces.

Related

Using sql to add to dates during a query

I have a table that keeps track of when particular events occur, and how long they last. For reasons I cannot fathom, it was designed to store the start date of the event, start time of the event, then the number of hours and minutes the event lasted. Like this:
EventStartDate | EventStartTime | TimeSpentHours | TimeSpentMinutes
Where EventStartDate is a dateTime with the hours/minutes always set to zero, so that, even though it's a date time, all the values are like "12/22/2016 00:00". The EventStartTime is a char(4) which is military time of the start of the event. TimeSpentHours is and int which is the total hours the event duration, and TimeSpentMinutes is an int for the number of minutes. Obviously the total time spent for the event is the hours plus the minutes.
The problem: I need to be able to, given a particular DateTime, find all the events that were occuring during that time. Put another way, given a particular DateTime I need to get all the events with a starting date and time that's greater than or equal to the given DateTime and less than or equal to an "end" date and time.
So I need to compute the "EndDateTime" based off the values in the database during the query. The database is SqlServer 2008 R2. I am using C# for WinForm application to query the data.
So far I have roughly:
public static List<ImportantEvents> GetEventsDuringDateTime(DateTime timeOfEvent)
{
using (SqlConnection sqlConn = getAndOpenSqlConn())
{
string theEventTime = timeOfEvent.ToString("hhmm");
string sqlStmt = "SELECT EVENT_ID, AGENCY, EVENTSTARTDATE, ACTNOTE, EVENTSTARTTIME, TIMESPENTHOURS, TIMESPENTMINUTES FROM EVENTSMAIN WHERE((EVENTSTARTDATE<= #MYEVENTDATETIME AND EVENTSTART TIME< #ACTTIME) AND ...";"
}
}
(the above SQL obviously won't work and is where I am stuck...)
My question is: how can I, in the query, add the EVENTSTARTTIME to the EVENTSTARTDATE to create a new "temporary" column, then add the TIMESPENTHOURS and TIMESPENTMINUTES to that column into another new "temporary" column, to then query against given a specific DateTime value???
It is possible to achieve this in a single query with a common-table expression like this:
With StartAndEndTimes As (
Select Event_ID,
EventStart = DateAdd(Minute, Convert(int, Right(EventStartTime, 2)), DateAdd(Hour, Convert(int, Left(EventStartTime, 2)), EventStartDate)),
EventEnd = DateAdd(Minute, Convert(int, Right(EventStartTime, 2))+TimeSpentMinutes, DateAdd(Hour, Convert(int, Left(EventStartTime, 2))+TimeSpentHours, EventStartDate))
From EventsMain)
Select Event_Id, EventStart, EventEnd, <<add other fields here>>
From StartAndEndTimes
Where EventStart <= #MyEventDateTime
And EventEnd > #MyEventDateTime;
Basically you can extract the hours and minutes from the start time and add them to the start date to get a true, datetime, start date. Similar with the end date. It is not necessary to use common-table expression here, but it does make the code more readable. Then you just do the ordinary date comparison to your input parameter.
Here I have disected parts of the final query. You will need to put the final part into your query wherever you need it.
SELECT Combined = EVENTSTARTDATE + EVENTSTARTTIMEFROM FROM EventsMain
SELECT CombinedWithHour = DATEADD(hh, TIMESPENTHOURS, Combined) FROM EventsMain
SELECT CombinedWithMinute = DATEADD(mi, TIMESPENTMINUTES, CombinedWithHour) FROM EventsMain
All together:
SELECT DATEADD(mi, TIMESPENTMINUTES, DATEADD(hh, TIMESPENTHOURS, EVENTSTARTDATE + EVENTSTARTTIME)) FROM EventsMain

How to find time differences between two time in c#

I have a form that gives me time_in and time_out hours of all staff members. Time_in and time_out also sql tables. Basically form returns the database table values. What I would like to do is to display the work hour of them. Work hour can be get the differences from time_out to time_in. I have two text boxes that display time in and Time_out. The third one should display work hour.
Here is what I have for time_out value for Wednesday:
//Selected TimeOutWednesday
SqlCommand TimeOutWednesdayMain = cs.CreateCommand();
TimeOutWednesdayMain.CommandText = "SELECT CONVERT(VARCHAR(8), time_out, 108) AS time_out FROM job_punch_card WHERE emp_key='" + listBoxNames.SelectedValue.ToString() + "'and punch_day= DATEADD(week, DATEDIFF(day, 0, getdate())/7, 2)";
Object TimeOutWednesdayMainTemp = TimeOutWednesdayMain.ExecuteScalar();
txtTimeInWed.Text = TimeOutWednesdayMainTemp.ToString();
This code gives me time_out for wednesday for the selected user from my listbox. I have the same code for time_in as well. What I couldn't do is to figure out how find the work hour? How can I display their work hour in a label or text box like I have above?
The DateTime types in OS are simples Integer values, you should make a arithmetical operation and get the Hours or TotalHours:
Hours get the integer portion of difference (dont lose parse your textboxes):
DateTime time_in;
DateTime.TryParse(time_in_TextBox.Text, out time_in);
DateTime time_out;
DateTime.TryParse(time_out_TextBox.Text, out time_out);
int hours = (time_in - time_out).Hours;
TotalHours get a double value with the exact difference in DateTimes:
DateTime time_in;
DateTime.TryParse(time_in_TextBox.Text, out time_in);
DateTime time_out;
DateTime.TryParse(time_out_TextBox.Text, out time_out);
double totalHours = (time_in - time_out).TotalHours;
I don't know if you're set on doing the time difference in SQL, but here's how you can do it in C# - though you would need to convert to a datetime object, not just a time (at least in this example).
See https://dotnetfiddle.net/DSuHmH :
using System;
public class Program
{
public static void Main()
{
DateTime startTime = new DateTime(2014, 1, 1, 1, 5, 1);
DateTime endTime = new DateTime(2014, 1, 1, 5, 10, 55);
TimeSpan ts = endTime - startTime;
Console.WriteLine(ts); // returns "04:05:54"
}
}
to specifically get the hours use:
ts.Hours;
To accomplish in sql you can do something like the following - again you'll need to convert your time to a datetime and then you can utilize the datediff function.
See: http://sqlfiddle.com/#!6/b7a7c/7
select convert(datetime, '2014-01-01 ' + startTime, 101),
convert(datetime, '2014-01-01 ' + endTime, 101),
datediff(
hh,
convert(datetime, '2014-01-01 ' + startTime, 101),
convert(datetime, '2014-01-01 ' + endTime, 101)
)
from test
Note that in the examples above i'm using an arbitrary date to accomplish creating a valid datetime
You should be able to do this in one query. This also shows the best practices for dealing with ADO.Net including putting your sql objects in using statements and passing values into your query as a parameter. Additionally you'll have to use ExecuteReader to get more than one value back and you can add checking for retrieving more or less than 1 row.
using (var cs = new SqlConnection("your connection string"))
{
cs.Open();
using (var command = cs.CreateCommand())
{
command.CommandText =
#"SELECT
time_in,
time_out,
DATEDIFF(minute, time_in, time_out) As minutesWorked
FROM job_punch_card
WHERE emp_key=#EMPKEY
and punch_day= DATEADD(week, DATEDIFF(day, 0, getdate())/7, 2)";
command.Parameters.AddWithValue(
"#EMPKEY",
listBoxNames.SelectedValue.ToString());
using (var reader = command.ExecuteReader())
{
if (!reader.HasRows)
{
// There was no match for your key
}
reader.Read();
DateTime timeIn = reader.GetDateTime(0);
DateTime timeOut = reader.GetDateTime(1);
int minutesWorked = reader.GetInt32(2);
if (reader.Read())
{
// There was more than one match on key
}
}
}
}
You can get the time difference, in minutes, using this:
DATEDIFF(MINUTE, #punch_day, #time_out)
This will return the total minutes between the two dates. If you need hours, divide it by 60. If you need days, then divide it by (60*24). Should you need weeks, divide it by (60*24*7). If you need years, divide it by (60*24*365). You get the idea, I hope!
Check out this example:
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
SELECT #StartDate = '12/9/2014 11:04am'
SELECT #EndDate = '12/10/2014 1:38pm'
SELECT DATEDIFF(MINUTE, #StartDate, #EndDate) AS TotalMinutes,
DATEDIFF(MINUTE, #StartDate, #EndDate) / 60 AS TotalHours,
DATEDIFF(MINUTE, #StartDate, #EndDate) / (60*24) AS TotalDays

Query to display +- 2 days of data but return only selected date itself

I would like to send a MySQL query where I choose a date from my C# programming comboBox e.g. 04/06/2014. Then result should show +-2days including 04/06/2014 itself. i.e. result will ended up showing data from 02/06/2014 till 06/06/2014 (a total of 5 days) in my dataGridView. My MySQL command below shows only the data for 04/06/2014, can someone kindly correct my code? Any help would be much appreciated!
Note: Assuming the 04/06/2014 will be replaced by my C# code comboBox_stockDates.SelectedItem.ToString()
SELECT Prices_Date, Prices_Time, Prices_Open
FROM tableprices
WHERE Ticker_ID = 732
AND DATE_ADD(STR_TO_DATE('04/06/2014', '%d/%m/%Y'), INTERVAL - 2 DAY)
AND DATE_ADD(STR_TO_DATE('04/06/2014', '%d/%m/%Y'), INTERVAL - 1 DAY)
AND Prices_Date = STR_TO_DATE('04/06/2014', '%d/%m/%Y')
AND DATE_ADD(STR_TO_DATE('04/06/2014', '%d/%m/%Y'), INTERVAL + 1 DAY)
AND DATE_ADD(STR_TO_DATE('04/06/2014', '%d/%m/%Y'), INTERVAL + 2 DAY)
ORDER BY Prices_Date ASC, Prices_Time ASC;
Your SELECT filters only the column Price_Date and current date. This one should work for you:
SELECT Prices_Date,
Prices_Time,
Prices_Open
FROM tableprices
WHERE Ticker_ID = 732
AND Prices_Date >= DATE_ADD (STR_TO_DATE ('04/06/2014', '%d/%m/%Y'), INTERVAL -2 DAY)
AND Prices_Date <= DATE_ADD (STR_TO_DATE ('04/06/2014', '%d/%m/%Y'), INTERVAL +2 DAY)
ORDER BY Prices_Date ASC, Prices_Time ASC;
For using the indexes of your table effectively (if there are any) it's better to convert the dates before the query as Chris suggested.
Any reason you can't do the conversion in C#? Seems cleaner.
Then it'd be a select from table where date greater than or equal and date less than or equal.
C# Code:
var dt = DateTime.ParseExact(comboBox_stockDates.SelectedItem.ToString(), "dd/MM/yyyy", System.Globalization.CultureInfo.InvariantCulture);
var start = dt.AddDays(-2);
var end = dt.AddDays(2);
Then select:
SELECT prices_date,
prices_time,
prices_open
FROM tableprices
WHERE ticker_id = 732
AND ( prices_date >= [startdate]
AND prices_date <= [enddate] )
ORDER BY prices_date ASC,
prices_time ASC;
Will this not work for you?

How to get data from the previous month result in SQL Server

I have 2 tables ms and fr.
ms contains columns pid,month, and totalsales, while fr contains pid, month, and forecast.
In both tables, each pid has 12 record based on month.
I actually want to calculate the demand where the formula is (0.3 * totalsales) + (0.7 * previous month result of forecast). The previous month result of forecast is like when the user choose pid 2 and month 2, then it will take the forecast result from month 1 as its calculation data.
I tried it already but the desired result is not returned:
select
((0.3 * totalsalesamount) + (0.7 * forecastdemand)) as demand
from
Monthlysales, forecastreorder
where
Monthlysales.P_ID = forecastreorder.Productid
and Monthlysales.P_ID = 1
and forecastreorder.Month = 2
When I execute the code above the result is based on their each forecast result. For example, when I choose pid 1, month 2, then it will take the forecast result from month 2 also. meanwhile i want it to take the forecast result from month 1 as its calculation data.
Try this to get previous month in sql
SELECT Convert(datetime, DateAdd(month, -1, Convert(date, GetDate())));
Using a similar table but with a year field, using ISNULL for no found data from previous moth, presume the previous is the month sales.
SELECT
0.3 * ms.totalsalesamount + 0.7 * ISNULL(fr.forecastdemand, ms.totalsalesamount) as demand
FROM
ms
LEFT OUTER JOIN
fr ON ms.pid = fr.pid
AND fr.month = CASE WHEN ms.month > 1 THEN ms.month - 1 ELSE 12 END
AND fr.year = CASE WHEN ms.month > 1 THEN ms.year ELSE ms.year - 1 END

How to convert string to datetime in sql server

I want to count total time in hh:mm:ss format. and I have minutes in int like (465).
I made:
CONVERT(varchar, CONVERT(datetime, cast(cast(TotalMin/60 as int) as nvarchar(50)) + ' : ' + cast(TotalMin%60 as nvarchar(50))),108) AS TotalMin
but it shows below error. Not in SQL Server but when I run code in c#:
Conversion failed when converting date and/or time from character
string.
You can use this code to get the string in SQL Server. It will convert hours and minutes and add 00 for seconds as you don't have them (you're using integer value for minutes):
declare #min int = 465
select right('0' + cast(#min/60 as varchar(2)),2)
+ ':'
+ right('0' + cast((#min - (#min/60)*60) as varchar(2)),2)
+ ':00'
It will work for up to 5999 minutes (99 hours and 59 minutes).
If you need a Unicode version:
declare #min int = 465
select right(N'0' + cast(#min/60 as nvarchar(2)),2)
+ N':'
+ right(N'0' + cast((#min - (#min/60)*60) as nvarchar(2)),2)
+ N':00'
Try this:
TimeSpan t = TimeSpan.FromMinutes( TotalMin);
and see this for more
UPDATE MyTable SET MyDate = CONVERT(datetime, '2009/07/16 08:28:01', 120)
For a full discussion of CAST and CONVERT, including the different date formatting options, see the MSDN Library Link below:
http://msdn.microsoft.com/en-us/library/ms187928.aspx
This will help you
You want to multiply out to milliseconds as the fractional part is discarded.
SELECT DATEADD(ms, 121.25 * 1000, 0)
If you want it without the date portion you can use CONVERT, with style 114
SELECT CONVERT(VARCHAR, DATEADD(ms, 121.25 * 1000, 0), 114)

Categories

Resources