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.

 All Forums
 General SQL Server Forums
 New to SQL Server Programming
 Dateconversion

Author  Topic 

OWSQL
Starting Member

27 Posts

Posted - 2011-07-04 : 03:48:28
Hi
I need to convert dates to express the first date in the month. Now the data I work on has a column with different dates within in the month, but in order for me to use this datefield in excell i need all dates to be the 1st. So for instance this date "2011-08-14 00:00..." needs to be "2011-08-01 00:00..."
Any ideas on how to do this easy?

Thanks

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2011-07-04 : 03:54:24
SELECT DATEADD(MONTH, DATEDIFF(MONTH, '19000101', Col1), '19000101')
FROM dbo.Table1


N 56°04'39.26"
E 12°55'05.63"
Go to Top of Page

OWSQL
Starting Member

27 Posts

Posted - 2011-07-04 : 04:50:28
Perfect, Thanks.
Go to Top of Page

jcelko
Esteemed SQL Purist

547 Posts

Posted - 2011-07-04 : 15:56:48
Are you using the DATE data type? Start doing that; it make life so much easier than carry "00:00:00.00" in a DATETIME field (note: the part of a temporal data type are called fields in Standard SQL and should not be confused with columns or the fields in the re3cords of file systems).

The fastest way is to build a look-up table with the first and last day of months in your time frame, then use a BETWEEN predicate in a JOIN with the target table. You can fill in this table with a spreadsheet for 20, 50 or 100 years easily.

Doing this with temporal function calls will not port, cannot be optimized and leads to row-by-row processing.

--CELKO--
Books in Celko Series for Morgan-Kaufmann Publishing
Analytics and OLAP in SQL
Data and Databases: Concepts in Practice
Data, Measurements and Standards in SQL
SQL for Smarties
SQL Programming Style
SQL Puzzles and Answers
Thinking in Sets
Trees and Hierarchies in SQL
Go to Top of Page

madhivanan
Premature Yak Congratulator

22864 Posts

Posted - 2011-07-05 : 04:19:16
<<
Are you using the DATE data type? Start doing that;
>>

Note that this datatype is not available in versions prior to 2008

Madhivanan

Failing to plan is Planning to fail
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2011-07-05 : 05:01:46
I have an idea. Let's performance test the two above given solutions.
-- Populate a 1,200 row calendar table
CREATE TABLE #Calendar
(
FromDate DATE NOT NULL,
ToDate DATE NOT NULL,
YearMonth INT NOT NULL
)

INSERT #Calendar
(
FromDate,
ToDate,
YearMonth
)
SELECT DATEADD(MONTH, m.Number, DATEADD(YEAR, y.Number, '20000101')),
DATEADD(MONTH, 1 + m.Number, DATEADD(YEAR, y.Number, '20000101')),
100 * (2000 + y.Number) + m.Number + 1
FROM master..spt_values AS y
INNER JOIN master..spt_values AS m ON m.Type = 'P'
AND m.Number BETWEEN 0 AND 11
WHERE y.Type = 'P'
AND y.Number BETWEEN 0 AND 99

CREATE UNIQUE CLUSTERED INDEX UCX_Calendar ON #Calendar (FromDate, ToDate, YearMonth)

-- Populate a 8,000,000 row orders table
CREATE TABLE #Orders
(
CustomerID INT NOT NULL,
OrderDate DATETIME NOT NULL,
Amount MONEY NOT NULL
)

INSERT #Orders
(
CustomerID,
OrderDate,
Amount
)
SELECT ABS(CHECKSUM(NEWID())),
DATEADD(SECOND, ABS(CHECKSUM(NEWID())) % 60, DATEADD(MINUTE, ABS(CHECKSUM(NEWID())) % 52596000, '20000101')),
ABS(CHECKSUM(NEWID())) / 10000E
FROM master..spt_values AS v1
INNER JOIN master..spt_values AS v2 ON v2.Type = 'P'
AND v2.Number BETWEEN 0 AND 199
INNER JOIN master..spt_values AS v3 ON v3.Type = 'P'
AND v3.Number BETWEEN 0 AND 199
WHERE v1.Type = 'P'
AND v1.Number BETWEEN 0 AND 199

CREATE UNIQUE CLUSTERED INDEX UCX_Orders ON #Orders (CustomerID, OrderDate)

-- Solution by Peso
SELECT DATEADD(MONTH, theMonth, 0) AS YearMonth,
theAmount AS Amount
FROM (
SELECT DATEDIFF(MONTH, 0, OrderDate) AS theMonth,
SUM(Amount) AS theAmount
FROM #Orders
GROUP BY DATEDIFF(MONTH, 0, OrderDate)
) AS d
/*
(1200 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0.
Table '#Orders'. Scan count 17, logical reads 31849.

SQL Server Execution Times:
CPU time = 5772 ms, elapsed time = 388 ms.
*/


-- Solution by Celko
SELECT c.YearMonth,
SUM(o.Amount) AS Amount
FROM #Calendar AS c
INNER JOIN #Orders AS o ON o.OrderDate >= c.FromDate
AND o.OrderDate < c.ToDate
GROUP BY c.YearMonth
/*
(1200 row(s) affected)
Table 'Worktable'. Scan count 1200, logical reads 24162377.
Table '#Calendar'. Scan count 17, logical reads 13.
Table '#Orders'. Scan count 1, logical reads 31849.

SQL Server Execution Times:
CPU time = 33025 ms, elapsed time = 31425 ms.
*/

DROP TABLE #Calendar,
#Orders

Let's see what the results are.

1) Peso uses 6 times less CPU
2) Peso uses 760 times less reads
3) Peso is 80 times faster



N 56°04'39.26"
E 12°55'05.63"
Go to Top of Page

Lumbago
Norsk Yak Master

3271 Posts

Posted - 2011-07-05 : 05:15:32
Now that's what I call a pretty solid BURN!

- Lumbago
My blog-> http://thefirstsql.com/2011/02/07/regular-expressions-advanced-string-matching-and-new-split-function-sql-server-2008-r2/
Go to Top of Page
   

- Advertisement -