Update 2 million rows for 1 column - c#

I have a table with approximately 2 million records. I have to loop through each record and update the effective date. I need to set the day to the first of the month for each date.
If the current date is the first of the month, then ignore.
i.e.
07/01/2018
07/21/2018 => 07/01/2018
08/11/2018 => 08/01/2018
Currently, I'm writing this as a C# program and it taking way too long.
Is there a better solution?

Just use DATEADD() and DATEDIFF() combination to get the first of the month date
UPDATE t
SET datecol = DATEADD(MONTH, DATEDIFF(MONTH, '1900-01-01', datecol), '1900-01-01')
FROM yourtable t;

It could be as simple as:
Update myTable
set myDate = DateAdd(day, 1-Day(myDate), myDate)
where day(myDate) > 1;

Related

Store DayOfWeek data in SQL Server

I want to save the DayOfWeek data as a column in a SQL Server table. Is this possible? ATM I'm saving an int and converting to DayOfWeek with a switch method, but I wish I could save and retrieve the data directly from the database.
UPDATE
I will try to explain. The user creates a recurring event, usually 2 times a week, for example, Monday and Friday. I want to create (on code run) all the recurring events in a given month, SO I want to store the DayOfWeek in SQL because for every event user can register if another user were present, late or so on..
Here a part of the code:
public static List<int> GetAttendance(int year, int month, DayOfWeek doW_1, DayOfWeek doW_2)
{
var days = DateTime.DaysInMonth(year, month);
var attendances = new List<int>();
for (int currentDay = 1; currentDay <= days; currentDay++)
{
var day = new DateTime(year, month, currentDay);
if (day.DayOfWeek == doW_1 || day.DayOfWeek == doW_2)
{
attendances.Add(currentDay);
}
}
return attendances;
}
doW1 and 2 comes from a little converter method made by me who read in db the integer stored by the user to create the recurring events.
UPDATE 2: I want to store data this way because I will use them for PREDICT future events by user inputs. Clear now?
You have two options.
Store your date value in a Date or DateTime columns and when querying, write queries with a where clause something like
WHERE DATENAME(WEEKDAY, DateColumn ) = 'Sunday'
But this will not be a sargable expression and on bigger data sets the query performance will be bad.
You can also store the week day in a Varchar(9) column and again use DATENAME() to extract the Week Day name from your date values at the time of Insert/update.
You can index this column and write simple queries like
SELECT * FROM Table
WHERE DateColumName = 'Sunday'
This option is commonly used in data warehouse environment where reducing data redundancy is not the goal but best read performance is the goal.
Keep storing it as an int, but you can get rid of your switch by just casting your saved int like so:
DayOfWeek day = DayOfWeek.Friday;
int temp = (int)day;
day = (DayOfWeek)temp;
Console.WriteLine(day); // Friday
Save it as a Date Column and use the following SQL functions to parse the WeekDay ID or WeekDay Name.
Using a date keeps your data structure understandable.
SELECT Datepart(weekday, Getdate())
SELECT Datename(weekday, Getdate())

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

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?

Search data only day value of date

Is it possible to search a data by day or month value of a date type value in mysql and c#.net.please can any one help me?
You can use DAY and MONTH functions:
SELECT *
FROM yourtable
WHERE DAY(date_column) = 1
or
SELECT *
FROM yourtable
WHERE MONTH(date_column) = 1
have a look at MySQL date and time functions.

How to update column in SQL Server 30 days from stored date on form load?

I want to take the rows with a createDate 30 days old and change the bit value IsExpired to 1. How do I accomplish this?
Here is the query I have tried:
UPDATE [mydb].[dbo].[mytable]
SET IsExpired = 1
WHERE CreateDate > (time, SYSDATETIME(GETDATE(CreateDate)+30))
The CreateDate column has a datetime string stored within it from a C# project. For example the value stored in the first row is 2013-05-29 14:59:48.000. When I execute it in SQL I get an error
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near ','.
Try something like this:
UPDATE [mydb].[dbo].[mytable]
SET IsExpired = 1
WHERE CreateDate < dateadd(dd, -30, getdate())
The following should match where the CreateDate field is less than 30 days prior to the current date of your SQL server. You may want to use GETUTCDATE() if you store your times in UTC.
UPDATE [mydb].[dbo].[mytable] SET IsExpired=1
WHERE CreateDate < DATEADD(DAY, -30, GETDATE())
Try below Query:
UPDATE [mydb].[dbo].[mytable] SET IsExpired=1 WHERE CreateDate < DATEADD(dd, -30, GETDATE())
Also this post will help you to know about DATEADD().
First I assumed that Skullomania is trying to get 30 days of CreateDate. Later from Scott Chamberlain comments, I got the point of user.
You can try:
UPDATE [mydb].[dbo].[mytable]
SET IsExpired=1
WHERE CreateDate = DATEADD(MONTH, -1, GETDATE())

Categories

Resources