Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
gena_mak
Starting Member
26 Posts |
Posted - 2010-02-05 : 14:34:10
|
| HiI inherited quite complex system that I can not change at this stage. It uses a lot of sub-queries and I feel that there is a better way to construct such queries so, may be someone will be kind enough to advice.Here is the table #tCustomerPayments that stores customer weekly payments over one year from Jan 1 to Dec 31. These payments can change over time and in some cases retroactively. When new payment is added starting with some date, it is inserted in proper date interval starting with that date and ending with year end (query #13), and all following records for this customer get overridden by setting active_record field to the customerpayment_id of newly inserted record (query #15). In query #14 dates are aligned in proper sequence. I tried to simplify the queries in question.Here is the definition:=====================================================================declare @newID intcreate table #tCustomerPayments (customerpayment_id int not null identity(1,1), customer_id int,amount float, start_date datetime, end_date datetime, active_record int)set nocount on-- populate table-- query #1 customer 1insert into #tCustomerPayments (customer_id, amount, start_date, end_date)values (1, 200, '1/1/2009', '2/11/2009')-- query #2insert into #tCustomerPayments (customer_id, amount, start_date, end_date)values (1, 100, '2/12/2009', '7/21/2009')-- query #3insert into #tCustomerPayments (customer_id, amount, start_date, end_date)values (1, 80, '7/22/2009', '9/21/2009')-- query #4insert into #tCustomerPayments (customer_id, amount, start_date, end_date)values (1, 140, '9/22/2009', '10/17/2009')-- query #5insert into #tCustomerPayments (customer_id, amount, start_date, end_date)values (1, 280, '10/18/2009', '10/18/2009')-- query #6insert into #tCustomerPayments (customer_id, amount, start_date, end_date)values (1, 290, '10/18/2009', '10/18/2009')-- query #7insert into #tCustomerPayments (customer_id, amount, start_date, end_date)values (1, 250, '10/19/2009', '12/31/2009')-- customer 2-- query #8insert into #tCustomerPayments (customer_id, amount, start_date, end_date)values (2, 1200, '1/1/2009', '5/25/2009')-- query #9insert into #tCustomerPayments (customer_id, amount, start_date, end_date)values (2, 25, '5/26/2009', '11/29/2009')-- query #10insert into #tCustomerPayments (customer_id, amount, start_date, end_date)values (2, 400, '11/30/2009', '12/31/2009')-- customer 3-- query #11insert into #tCustomerPayments (customer_id, amount, start_date, end_date)values (3, 700, '1/1/2009', '12/31/2009')-- end of populate table-- pull all active records-- query #12SELECT * FROM #tCustomerPayments WHERE active_record IS NULL ORDER BY customer_id, customerpayment_id-- updates to payment amounts done in Jan, 2010 retroactively -- customer's 1 payments become $150 starting 8/23/2009 to the end of the year-- query #13insert into #tCustomerPayments (customer_id, amount, start_date, end_date)values (1, 150, '8/23/2009', '12/31/2009')SET @newID = @@IDENTITY-- update record with start date earlier than 8/23/2009 and end_date later than 8/23/2009 to make end date 8/22/2009 to make proper sequence -- query #14UPDATE #tCustomerPayments SET end_date = DateAdd(dd,-1,'8/23/2009') WHERE customer_id = 1 AND start_date < '8/23/2009' AND end_date > '8/23/2009' AND active_record IS NULL-- all amounts that were active after that date become inactive by setting active_record to the @@identity of just inserted record-- query #15UPDATE #tCustomerPayments SET active_record = @newID WHERE customer_id = 1 AND start_date > '8/23/2009'-- pull all active records-- query #16SELECT * FROM #tCustomerPayments WHERE active_record IS NULL ORDER BY customer_id, customerpayment_id-- query #17SELECT * FROM #tCustomerPayments WHERE active_record IS NOT NULL ORDER BY customer_id, customerpayment_id------------------------------------------------------------------------------ we need to get latest payment data for customer #1-- query #18SELECT * FROM #tCustomerPayments c WHERE customer_id = 1 AND active_record IS NULL AND customerpayment_id = ( SELECT TOP 1 customerpayment_id FROM #tCustomerPayments WHERE customer_id = c.customer_id AND active_record IS NULL ORDER BY end_date DESC, customerpayment_id DESC )-- we need to get payment data for customer #1 as of 5/21/2009 (May 21, 2009)-- query #19SELECT * FROM #tCustomerPayments c WHERE customer_id = 1 AND active_record IS NULL AND customerpayment_id = ( SELECT MAX(customerpayment_id) -- max() is used because in some cases payment can change few times in one day as in insert query #5 and #6 FROM #tCustomerPayments WHERE customer_id = c.customer_id AND active_record IS NULL AND DateDiff(dd,start_date,'5/21/2009')>=0 AND DateDiff(dd,'5/21/2009',end_date)>=0 )------------------------------------------------------------------------drop table #tCustomerPayments set nocount off=====================================================================Basically, in queries number #18 and #19 to pull latest customer record or as of some date, used sub-query that relies on customerpayment_id. It works fine but, is there better way to pull it without using this sub-query?Thank you |
|
|
Kristen
Test
22859 Posts |
Posted - 2010-02-06 : 01:08:23
|
haven't had time to look at this in detail, but one thing I spotted:AND DateDiff(dd,start_date,'5/21/2009')>=0AND DateDiff(dd,'5/21/2009',end_date)>=0 this is always better done as:AND start_date < '20090522'AND end_date >= '20090521' This allows SQL to use any available index on start_date or end_date (whereas if you include the date column in function then indexes are not used).Note that the start condition is LESS THAN 'one-day-after-the-end-point' - this allows the start_date to include a time element, i.e. up to 23:59.I've also changed your string dates to 'yyyymmdd' which is the only unambiguous implicit format that is guaranteed to work. Your style is probably fine on the server you use, but is not transportable to servers with different locale settings. (Date strings in m/d/y order can be explicitly cast of course) |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2010-02-06 : 06:14:29
|
for query 18 isnt this enough?SELECT TOP 1 *FROM #tCustomerPaymentsWHERE customer_id = 1AND active_record IS NULLORDER BY end_date DESC, customerpayment_id DESC and for query 19SELECT TOP 1 * FROM #tCustomerPayments cWHERE customer_id = 1AND active_record IS NULLAND start_date < '20090522'AND end_date >= '20090521'ORDER BY customerpayment_id DESC |
 |
|
|
gena_mak
Starting Member
26 Posts |
Posted - 2010-02-08 : 09:11:03
|
| KristenI am not concerned about day format as I have ODBC wrapper before the date is applied as argument to stored procedures, functions or queries. As for DateDiff(), I know some advice against that, some... for. The DateDiff() helps to establish date frame that relies on day only, I dont care about time and this is very important, especially its important because the system is used over few time zones.visakh16SELECT TOP 1... I had it failed in couple of cases, it is important to get this unique customerpayment_id in WHERE clause.For my question, I was thinking in order to improve performance, perhaps to switch to derived tables or views (can be too much work). May be some sort of grouping would work better. |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2010-02-08 : 09:22:00
|
| SELECT TOP 1... I had it failed in couple of cases, it is important to get this unique customerpayment_id in WHERE clause.sorry didnt understand why it failed. can you explain that? |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2010-02-08 : 09:32:23
|
"I am not concerned about day format as I have ODBC convert funciton wrapper before the date is applied as argument to stored procedures, functions or queries."OK (but dates in string format, as examples on this forum for instance, will perform differently around the world )Is your application sending Dates via ODBC as just the Date, or including a time also - i.e. a DateTime?If it is just the date thenAND start_date < DATEADD(Day, 1, @CutoffDate)AND end_date >= @CutoffDate will include values for start_date (including any time) that is on, or before, @CutoffDate - that is to say earlier than midnight-following the cutoff date; and end_date is midnight on the @CutoffDate (i.e. midnight at the start of the cutoff date) or later.If the parameters from your application include time components as well the parameters can be "rounded" to midnight to remove them:AND start_date < DATEADD(Day, DATEDIFF(Day, 0, @CutoffDate), 1)AND end_date >= DATEADD(Day, DATEDIFF(DAy, 0, @CutoffDate), 0) both those methods should use indexes available for the Start/End date columns."As for DateDiff(), I know some advice against that, some... for."I'd be interested to know anything against please.In this context if you apply DateDiff() to the columns e.g.AND DateDiff(dd,start_date, @CutoffDate)>=0AND DateDiff(dd,@CutoffDate, end_date)>=0 indexes will not be used in the query plan, resulting in a scan of all rows in the table - which, for a large table, will be much slower than using a query plan which uses the indexes."The DateDiff() helps to establish date frame that relies on day only, I dont care about time and this is very important, especially its important because the system is used over few time zones."OK, my examples did assume that the time was to be ignored |
 |
|
|
gena_mak
Starting Member
26 Posts |
Posted - 2010-02-08 : 09:55:34
|
| visakh16:It failed to pull right record, I cant remember particular. I will try to find it. The thing is, my example here is quite simplified. The structure of the tables involved is quite a bit more. Here we have few more joined tables for payment period for expample where payment period is by itself has unique primary key which is has foreign key present in what is here #tCustomerPayments.Basically in very short whithin context of the quesion, as it takes lot more to expand, it looks like that:customer table (top table for customer)payment plan (top table for plan, there are also groups of payments and item payments within groups...)payment plan -> payment periodpayment group -> payment itemcustomer -> payment period -> payments (junction table for customer payments within payment period on this plan, there are multiple payments for multiple items, read records for each customer and customer can change items, options, pay methods...) if I expand only little bit more:create table #tCustomerPayments (customerpayment_id int not null identity(1,1), cust_payperiod_id int foreign key tCustPayPeriods,payitem_id int foreign key tPayItems,payitem_option_id int foreign key tPayOptions,paymethod_id int foreign key tPaymethods,customer_id int foreign key tCustomers,amount float, start_date datetime, end_date datetime, active_record int)So, when I put everything together and try to pull right record, the query looks quite more complex than I presented here. So, my question is sort of more general on how to improve performance, as I see too many sub-selects. |
 |
|
|
gena_mak
Starting Member
26 Posts |
Posted - 2010-02-08 : 10:14:50
|
quote: Originally posted by Kristen "I am not concerned about day format as I have ODBC convert funciton wrapper before the date is applied as argument to stored procedures, functions or queries."OK (but dates in string format, as examples on this forum for instance, will perform differently around the world )Is your application sending Dates via ODBC as just the Date, or including a time also - i.e. a DateTime?If it is just the date thenAND start_date < DATEADD(Day, 1, @CutoffDate)AND end_date >= @CutoffDate will include values for start_date (including any time) that is on, or before, @CutoffDate - that is to say earlier than midnight-following the cutoff date; and end_date is midnight on the @CutoffDate (i.e. midnight at the start of the cutoff date) or later.If the parameters from your application include time components as well the parameters can be "rounded" to midnight to remove them:AND start_date < DATEADD(Day, DATEDIFF(Day, 0, @CutoffDate), 1)AND end_date >= DATEADD(Day, DATEDIFF(DAy, 0, @CutoffDate), 0) both those methods should use indexes available for the Start/End date columns."As for DateDiff(), I know some advice against that, some... for."I'd be interested to know anything against please.In this context if you apply DateDiff() to the columns e.g.AND DateDiff(dd,start_date, @CutoffDate)>=0AND DateDiff(dd,@CutoffDate, end_date)>=0 indexes will not be used in the query plan, resulting in a scan of all rows in the table - which, for a large table, will be much slower than using a query plan which uses the indexes."The DateDiff() helps to establish date frame that relies on day only, I dont care about time and this is very important, especially its important because the system is used over few time zones."OK, my examples did assume that the time was to be ignored
KristenThe date gets to the query in this format {d '2010-02-04'} and in some cases when used in stored procedure with time. I mentioned before that I ingnore the time because we do not have requirement anywhere to use it, only DAY, MONTH, YEAR. I am reluctanct to switch to date data type in stored procedures, may be in future we might need time too, so I use datetime in functions and procedures.Thank you for pointing about indexes. I will try to experiment to see if it helps to improve performance. |
 |
|
|
Transact Charlie
Master Smack Fu Yak Hacker
3451 Posts |
Posted - 2010-02-08 : 10:18:35
|
Hi gena_mak.I was going to suggest a few improvements but I've read over what Kristen and Visakh have posted and everything they say is great advice for the information you posted.This section:-- we need to get latest payment data for customer #1-- query #18SELECT * FROM #tCustomerPayments cWHERE customer_id = 1AND active_record IS NULLAND customerpayment_id = ( SELECT TOP 1 customerpayment_idFROM #tCustomerPaymentsWHERE customer_id = c.customer_idAND active_record IS NULLORDER BY end_date DESC, customerpayment_id DESC) Where visakh simplified this to get what he posted but this doesn't really make sense. Why would want to find the top 1 for a particular person this way?Were you actually wanting the TOP 1 details per customer in the table ordered by some set of columns? If so that isn't what you said you wanted.Kristen's advice on the date comparisons is gold and you seem to be completely ignoring it.If you want accurate help then my advice is to split the problem in smaller pieces. Post the *full* (not simplified) version of those problems and someone will not be able to resist showing how kewl he or she is by optimising them.Posting something that is different to what you actually want to fix is meaningless unless you get the root cause of the problem absolutely right. I think you are putting people off from helping you here.Here are a few questions that you can answer which will help people help you:---------------------------------1) Which version of SQL Server are you using? -- this is important as there are many methods of optimisation that work well in 2005 or later that are not available in 2000. In particular it is often easy to eliminate sub selects with either ROW_NUMBER() or OUTER/CROSS APPLY2) Please provide the full table structure (including any indices present) for the tables involved.3) Please provide the *actual* sql that you want to improve. There's nothing more likely to turn someone off from helping than when they post a solution and the OP says -- actually that isn't relevant because....4) If possible please provide some data. This doesn't have to be actual data and it's probably better from a security point of view that it isn't but it should be representative of your actual data.----------------If you do this then you'll get awesome help here. Your problems will vanish.I'm not having a go at you, but if you stop for a moment and have a look at your posts I think you'll find that you aren't coming across very well.Best of luck,Charlie===============================================================Msg 3903, Level 16, State 1, Line 1736The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION |
 |
|
|
gena_mak
Starting Member
26 Posts |
Posted - 2010-02-08 : 10:30:08
|
quote: Originally posted by Transact Charlie Hi gena_mak.I was going to suggest a few improvements but I've read over what Kristen and Visakh have posted and everything they say is great advice for the information you posted.This section:-- we need to get latest payment data for customer #1-- query #18SELECT * FROM #tCustomerPayments cWHERE customer_id = 1AND active_record IS NULLAND customerpayment_id = ( SELECT TOP 1 customerpayment_idFROM #tCustomerPaymentsWHERE customer_id = c.customer_idAND active_record IS NULLORDER BY end_date DESC, customerpayment_id DESC) Where visakh simplified this to get what he posted but this doesn't really make sense. Why would want to find the top 1 for a particular person this way?Were you actually wanting the TOP 1 details per customer in the table ordered by some set of columns? If so that isn't what you said you wanted.Kristen's advice on the date comparisons is gold and you seem to be completely ignoring it.If you want accurate help then my advice is to split the problem in smaller pieces. Post the *full* (not simplified) version of those problems and someone will not be able to resist showing how kewl he or she is by optimising them.Posting something that is different to what you actually want to fix is meaningless unless you get the root cause of the problem absolutely right. I think you are putting people off from helping you here.Here are a few questions that you can answer which will help people help you:---------------------------------1) Which version of SQL Server are you using? -- this is important as there are many methods of optimisation that work well in 2005 or later that are not available in 2000. In particular it is often easy to eliminate sub selects with either ROW_NUMBER() or OUTER/CROSS APPLY2) Please provide the full table structure (including any indices present) for the tables involved.3) Please provide the *actual* sql that you want to improve. There's nothing more likely to turn someone off from helping than when they post a solution and the OP says -- actually that isn't relevant because....4) If possible please provide some data. This doesn't have to be actual data and it's probably better from a security point of view that it isn't but it should be representative of your actual data.----------------If you do this then you'll get awesome help here. Your problems will vanish.I'm not having a go at you, but if you stop for a moment and have a look at your posts I think you'll find that you aren't coming across very well.Best of luck,Charlie===============================================================Msg 3903, Level 16, State 1, Line 1736The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION
CharlieThank you for input. I am not ingnoring, I am learning :)Its very helpful as I am not advanced SQL programmer, any advice is very helpful, just difficult to explain without the context. Easy part is we use SQL 2005.Now, I am trying to figure which part of the system to show here as it contains about 250 tables and, not to confuse people. |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2010-02-08 : 10:30:40
|
| "The date gets to the query in this format {d '2010-02-04'}"Perfect then!"I am reluctanct to switch to date data type in stored procedures, may be in future we might need time too, so I use datetime in functions and procedures."Ah, sorry if I implied changing datatype, I certainly didn't mean that, my suggestions are just designed to remove the time-part of a datetime datatype. I haven't used DATE datatype in SQL 2008 for anything yet either! |
 |
|
|
Transact Charlie
Master Smack Fu Yak Hacker
3451 Posts |
Posted - 2010-02-08 : 10:53:27
|
Gena_makIts good that you are on 2005. There will be lots of ways to remove subqueries.I'm posting this to illustrate Kristen's advice.This sql will build a dataset of random datesIF OBJECT_ID('tempDb..#testTable') IS NOT NULL DROP TABLE #testTableCREATE TABLE #testTable ( [Id] INT IDENTITY(1,1) PRIMARY KEY NONCLUSTERED , [startDate] DATETIME , [endDate] DATETIME )CREATE CLUSTERED INDEX IX_ID_START_END ON #testTable ([startDate], [endDate])GOINSERT #testTable ([startDate], [endDate])SELECT CAST(CAST(CAST(NEWID() AS VARBINARY(2)) AS INT) AS DATETIME) , CAST(CAST(CAST(NEWID() AS VARBINARY(2)) AS INT) AS DATETIME)FROM (SELECT 1 AS [1] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3]) a CROSS JOIN (SELECT 1 AS [1] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3]) b CROSS JOIN (SELECT 1 AS [1] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3]) c CROSS JOIN (SELECT 1 AS [1] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3]) d CROSS JOIN (SELECT 1 AS [1] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3]) e CROSS JOIN (SELECT 1 AS [1] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3]) f CROSS JOIN (SELECT 1 AS [1] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3]) g CROSS JOIN (SELECT 1 AS [1] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3]) hGOYou'll end up with a temp table with 3 to the eight rows of random dates. There is a clustered index over both dates but you can change that to suit your requirement. You need a lot of rows to make sure that the optimisation engine wouldn't just choose an index SCAN as the fastest method for all queries.You can then play with this to see the benefits that Kristen is talking about.Here is a short example script. The important bit is really the SET SHOWPLAN_ALL ON. This has to be the only command in a batch and you'll have to run it in the same Management Studio window the temp table was created in. You can then rerun the two SELECT statements below it to see the index usage.-- This must be the only command in the batch -- it shows you the execution plan and index useSET SHOWPLAN_ALL ONGO-- DATEDIFF EXAMPLE-- Find any rows with startdate of 2010-Jan-01SELECT *FROM #testTableWHERE DATEDIFF(DAY, [startDate], '20100101') = 0GO-- >= < EXAMPLESELECT *FROM #testTableWHERE [startDate] >= '20100101' AND [startDate] < '20100102' You should see that the second query (which will return the same results as the first) will use an INDEX SEEK whereas the first will use an INDEX SCAN. when you scan the index you have to look at the value of every row in the table. when you SEEK then you don't.Charlie===============================================================Msg 3903, Level 16, State 1, Line 1736The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION |
 |
|
|
Transact Charlie
Master Smack Fu Yak Hacker
3451 Posts |
Posted - 2010-02-08 : 10:56:19
|
Just a short note to say that with SET SHOWPLAN_ALL ON if you run the whole set of scripts again (the parts that generate the dates) then you'll get an errorMsg 2714, Level 16, State 6, Line 3There is already an object named '#testTable' in the database. You can ignore it -- if you look at your results tab you'll still see the execution plan.Here's the expected reslts1) For the DATEDIFF exampleEstimateRows EstimateIO EstimateCPU AvgRowSize729 NULL NULL NULL729 0.01868056 0.0073741 27 2) For the >= < ExampleEstimateRows EstimateIO EstimateCPU AvgRowSize1 NULL NULL NULL1 0.003125 0.0001581 27 So even on this very small dataset the IO costs are improved by a factor of 6. The CPU improvement is even better.Charlie===============================================================Msg 3903, Level 16, State 1, Line 1736The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION |
 |
|
|
gena_mak
Starting Member
26 Posts |
Posted - 2010-02-08 : 11:25:39
|
quote: SELECT *FROM #testTableWHERE DATEDIFF(DAY, [startDate], '20100101') = 0GO-- >= < EXAMPLESELECT *FROM #testTableWHERE [startDate] >= '20100101' AND [startDate] < '20100102'[/code]
CharlieMay be a dumb question but, just to make sure I covered that. Will this matter if server is located in one time zone and query is executed in another where in our time zone is 11:40PM (23:40) Feb 8, and somewhere where the query is executed its 5AM (5 O'clock) Feb 9?Gena |
 |
|
|
Transact Charlie
Master Smack Fu Yak Hacker
3451 Posts |
Posted - 2010-02-08 : 11:27:35
|
| doesn't matter -- the query is executed on the server. Even if you referenced a function like GETDATE() it would return the system time of the db server. As long as the dates in the table are accurate......Charlie===============================================================Msg 3903, Level 16, State 1, Line 1736The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2010-02-08 : 11:33:03
|
| "May be a dumb question but, just to make sure I covered that. Will this matter if server is located in one time zone and query is executed in another where in our time zone is 11:40PM (23:40) Feb 8, and somewhere where the query is executed its 5AM (5 O'clock) Feb 9?"I was going to raise that earlier, but thought it would just be clouding the issue ... maybe not ...Lets say you have offices in Europe and USA.If I am in Europe its 08-Feb and, lets say, its still 07-Feb in USA.Lets say the server is in USA.If I record some data what date is used? Do I manually enter the date (i.e. into your application), and thus I enter 08-Feb, or does the server allocate the date automatically - i.e. 07-Feb? or does the application use the date/time on my PC (which could be anything, of course, because my system clock could be wrong).When the clocks go forward/back that makes a further mess of things of course ... |
 |
|
|
Transact Charlie
Master Smack Fu Yak Hacker
3451 Posts |
Posted - 2010-02-08 : 11:40:11
|
| ah true -- I thought gena_mak meant that:With the same set of data and the same queryWould the results be different if run from a different client connection in different time zone.Charlie===============================================================Msg 3903, Level 16, State 1, Line 1736The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2010-02-08 : 11:45:56
|
| "I thought gena_mak meant that"Could be that too, I hadn't thought of that |
 |
|
|
gena_mak
Starting Member
26 Posts |
Posted - 2010-02-08 : 12:19:57
|
| Yea, I messed the quesiton up a bit. I meant to compare dates submitted from different time zones where the date is the same but time is different. I such cases even if one record would be submitted earlier but carry date stamp later than the other. However primary key (identity) will be greater value than the other one.Let say I am in Seattle and its 11AMSomeone else in New York and its 8AMI submitted my query and saved it with date stamp of 11AM on Feb 8 - record primary key is 22Someone else does the same after that and date stamp is 8AM - record primary key is 27In this case, will the server convert to its local time or will save 11AM and 8AM?Sorry if confused you, trying to manage few things here |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2010-02-08 : 12:30:26
|
"In this case, will the server convert to its local time or will save 11AM and 8AM?"If the Application includes the time with the Date that it sends to SQL server then that is exactly what SQL Server will store. 11AM for the data from Seattle, 8AM for the data from New York.If the application just sends the Date then the time will still be stored, but will be set to 00:00:00.If the application sends a record and says "User Current Server Time" - i.e. the equivalent of GetDate() - then SQL Server will store the current server time and ALL records created will be in ascending chronological order**. Then the user has to query using the Server Time - so if the user thinks they saved it at 8AM local time the actual Server Time would be different, and searching for an 8AM record will find nothing (or a different record )** Note that when the clocks go back you may get times repeated for that hour, and they won't be created in strict chronological order BUT ... if you ARE storing the time provided by the application (and NOT SQL Server's own time when the record is created) then you probably have other problems of the various PC's clocks being "unreliable" or "not set to the correct current time" |
 |
|
|
gena_mak
Starting Member
26 Posts |
Posted - 2010-02-08 : 13:24:02
|
| Application uses date only with ODBC date wrapper local to web application server and not time so, I guess its fine in that sense. However, the time is used when data is manipulated by stored procedures and functions where I use datetime datatype.My concern that when I compare dates straight with >= and =<, I can get erronious results as in some cases when time is used to bring up one record over another and I cant have it happened. That is why I use DateDiff(DAY...) function. Now, I see it causes table scan and I need to get away from this method. |
 |
|
|
Next Page
|
|
|
|
|