I have large tables, contains DateTime columns to store exact time of some events and actions in my application. In some cases, users can enter the date of an event.
I want to validate event sequences, find events by the time of happening, and such things.
If I order events by DateTime, it's time consuming in large data. If I order by Id, there's no guaranty that users data entry is ordered, also users are not responsible to determine the sequence (they just enter date time). I prefer to order by a numeric field instead of DateTime.
What do you suggest?
Ordering by DateTime columns should not be slow, even on large data, provided your database has that column indexed.
I would, personally, do the ordering directly on the DateTime (with an index on the db), but make sure that your LINQ queries limit the results to the appropriate date window.
Keep in mind that a datetime will be stored as an integer number of ticks since a fixed point in time (generally Jan. 1st 1970). To compare datetimes it is just an integer comparison of this single value, it doesn't need to compare year, month, day, etc. That is unless you're storing the date as a string, and not as a datetime.
My guess is that your database is internally storing the data sorted by ID, and that the ID is also indexed, which is why that's so quick. Your problem isn't sorting on a datatime, it's simply sorting on a non-ID column. As Reed suggested, you probably just need to index the column. It's also possible that you're doing something, somewhere, in a way that you shouldn't. It's hard to say what that might be without seeing the code, the DB configuration, etc.
Related
I am trying to retrieve the newest row created in the Primary Minute Metrics tables that is automatically created by Azure. Is there any way to do this without scanning through the whole table? The partition key is basically the timestamp in a different format. For example:
20150811T1250
However, there is no way for me to tell what the latest partitionkey is, so I can't just query by partition. Also, the row key is useless since all the rows have the same rowkey. I am completely stumped on how I would do this even though it seems like a really basic thing to do. Any ideas?
An example of a few partition keys of rows in the table:
20150813T0623
20150813T0629
20150813T0632
20150813T0637
20150813T0641
20150813T0646
20150813T0650
20150813T0654
EDIT: As a followup question. Is there a way to scan the table backwards? That would allow me to just get the first row scanned since that would be the latest row.
When it comes to querying data, Azure Tables offer very limited choices. Given that you know how the PartitionKey gets assigned (YYYYMMDDTHHmm format), one possible solution would be to query from current date/time (in UTC) minus some offset to current date/time and go from there.
For example, assuming start time is 03-Dec-2015 00:00:00. What you could do is try to fetch data from 02-Dec-2015 23:00:00 to 03-Dec-2015 00:00:00 and see if any records are returned. If the records are returned, you can simply take the last entry in the resultset and that would be your latest entry. If no records are found, then you move back by 1 hour (i.e. from 02-Dec-2015 22:00:00 to 02-Dec-2015 23:00:00) and fetch records again and repeat this till the time you find matching result.
Yet another idea (though a bit convoluted one) is to create another table and periodically copy the data from the main table to this new table. When you copy the data, what you would need to do is take the PartitionKey value, create a Date/Time object out of it, subtract that from DateTime.MaxValue. Calculate the ticks for this new value and use that as the PartitionKey for your new entity (you would need to convert that ticks into string and do some string prepadding so that all values are of same length). Now the latest entries will always be on the top.
I would like to understand the concept behind this.
I am making a database in c#. Now, I wish to have only date instead of date and time.
So, I went for the following command in sql query pane:
SELECT CONVERT(varchar, deal_start_date, 101) AS 'deal_start_date'
FROM client
The desired result comes but the data becomes read only and hence cant be edited.
Further, it does not stay permanently. I mean,
On clicking show table data again the date-time format comes.
Can any one tell me why the cells become read-only and how to keep the changes permanently through UI only??
Many thanks.
My guess on the read only part, is that since you are now converting the original value, you loose the link towards the column in the database. Just like a computed column can't be edited (how would you for example write to the column from the query that is defined as A+B as 'C'.
Inside what type of component are you showing this in your GUI? Maybe you can ahve your query remain as SELECT deal_start_date FROM client, and filter out the time part from your component?
Or, if you don't use the time in any other place in your application, change the column from datetime to date in the database.
I did not get a perfect answer but I found an alternative. I was trying with datetime datatype in MS SQL database. When I changed it to varchar(12), I got the desired result. i.e in date format.
(Thanks to insights provided by Øyvind Knobloch-Bråthen )
This is actually improper to follow as with size 12 in varchar, the time part is truncated.
(If the size of varchar is increased, the time part will be present)
But It served my purpose.
But I am still waiting for a correct answer,if any.
I have an application where I register some information into the database where I have a Column (DateTime). In this column I insert the date from a DateTimePicker.
Now I want to make a search button which searches according to the date chosen from Comboboxes... but in this Comboboxes I left only one option, to select MONTH and YEAR... how can I make an SELECT query that selects all information according to the Month and Year chosen from the ComboBoxes?
select * from <table>
where month(searchDate)=Month_from_box and Year(searchDate)=Year_from_box
However, depending on the size of your data, this might not be the fastest approach. If you data is in the 100's or even 1000 rows, this approach might be OK...
Another approach would be to build starting and ending dates in C# from your input and then perform a range search
select * from <table>
where searchDate between Start_date_from_C# and End_Date_from_C#
If you go that approach, be sure to consider the time portion, make it 0 in first date and 23:59:59 in the End Date
If you have an index on the date field, the second approach will be faster...
All solutions which use either the datepart or month and year functions make it impossible for the server to optimize the query by using an index.
The only valid solution in terms of performance is #Sparkys second approach using the between clause. He also described the problems arising with the time fraction. That is why I would prefer using a plain date column (instead of datetime). Then you can write
select *
from YourTable
where DateColumn between <FirstDayOfSelectedMonthAndYear>
and <LastDayOfSelectedMonthAndYear>
because when using a datetime column and the range of
between '20121201' and '20121231 23:59:59'
Everything after the last second of the year and midnight still gets discarded. Although it is very unlikely it is technically not correct.
#Nicarus suggests widening the ending time to 23:59:59,997'. This seems to work but is 'ugly' (but, wtf, it works!)
Make sure you store the combo values into Integer variables in your C# before putting them in the SQL query. As others have alluded, SQL Injection attacks are possible if you allow the direct user input to be placed inside a SQL String.
Assuming you have 2 int variables "intMonth", "intYear", and the field name of "dateFieldname", the following SQL should work.
SELECT *
FROM [table]
WHERE datepart[mm,dateFieldname] = intMonth
AND datepart[yyy,dateFieldname] = intYear
Something like this
Select * from tablename where
datepart(mm,datecolumnname)=#cmboxMonthvalue nd datepart(yyyy,datecolumnname)=#ComboboxYearvalue
I want to save entries to a database table depending on the DateTime entered. I have a different model and partial view for each month in the year. Users can create events, I want the events to be saved to the corresponding month table in the db so I can return it to the correct view.
So I need some sort of if statement that says 'if the month value of the entered DateTime is x save to tabel x, if y save to y' and so on.
The user will navigate from month to month and pick dates from a html table styled like a calendar, so the entries need to be inserted to the section of the calendar that corresponds to the datetime. This is just to explain why I need this functionality.
If someone can reccomend a more elegant and functional method of achieving this, go right ahead!
I'm sorry I don't have code to post, I have tried a number of ways and failed. I will post code tomorrow morning when I'm at my computer, but this seems quite simple and I'm very new to this lark so if someone could shed light now, that would be great.
Thanks in advance!
Don't break it out into 12 separate tables. Store them in a single table. You could create a computed column that tells you the month number by calculating it from the DateTime value you're already storing. If your REALLY need to, you can create 12 views off of this table rather easily but I'd take the approach of adding time parameters to your query's WHERE clause. Make sure you index on the DateTime column.
We're using LINQ to SQL and WCF for a new middle tier, and we're using Data Transfer Objects for passing over the wire rather than using the actual LINQ classes. I'm going to be using one or the other of the methods outlined here - Linq Table Attach() based on timestamp or row version - in order to ensure that updates work correctly and that concurrency is handled correctly.
To save you folks some reading time, essentially you can either use a timestamp/rowversion column in your table or have a datetime column with a default and an update trigger - either way it gets you a column that gets a newly generated value each time an insert or update occurs, and that column is the one used by LINQ to check for concurrency.
My question is - which one is better? We already have datetime columns for "UpdatedWhen" in many of our tables (but not all - don't ask), but would be adding in the defaults and the triggers, or we could just add the rowversion (we'd have to use the timestamp syntax for now, since we're still supporting SQL2005 for a while) to each table - either way we're modifying the DB in order to make it work, so I'd like to know whether there's a performance difference or any other important difference to note between these two alternatives. I've tried searching the web and here on SO, but no luck so far. Thanks.
I had to make the similar decision recently.
I tried rowversion solution first.
The disadvantages that I found:
Inconvenient usages in LINQ-to-SQL, I mapped the field to byte[]. The code does not look clean when you compare byte arrays
Theoretically rowversion can roll over and start from 0 again, so row with higher rowversion will not necessarily be older row
Rowversion is updated on any row update, which in my case was not desirable, I needed to exclude some columns to not affect row version. Having a trigger allows to implement any level of flexibility.
As a result I used datetime2 column with a default constraint and update trigger to set the value to sysutcdatetime().
This type has accuracy 100 nanoseconds (precision 7 digits - 23:59:59.9999999).
Although it is possible, I never saw generation of the same value twice yet. But in my case it will not hurt if there will be duplicates. If it was important to me, I would add unique constraint, and see if this ever fails.
I used sysutcdatetime() as this value would not be affected by daylight saving.
I would lean towards using timestamp column for concurrency checks. One - triggers would have some impact upon performance and two - with date time column you'll be limiting yourself to the precision of DateTime column in SQL and C#.
MSDN:
datetime values are rounded to increments of .000, .003, or .007 seconds...
You may want to look at SO: Is there any difference between DateTime in c# and DateTime in SQL server? and MSDN: datetime (Transact-SQL) for more info.