SQL: How to Group by Custom Year - sql

For simplicities sake, I'll make up a similar example to what I have:
Let's say a db has a table of orders with an OrderDate field and a Company field. Then there's a table of Companies and each record has a YearEndingDate (which signifies that the year ends on that date each year, e.g. 6/6).
I need to add up all of the orders for each year.
I assume it would have to be something like this but I can't quite figure it out:
SELECT SUM(orderValue),
CASE WHEN orderDate <= YearEndingDate THEN DatePart(year, orderDate)
CASE WHEN orderDate > YearEndingDate THEN DatePart(year, orderDate) + 1
END as Year
FROM Orders
INNER JOIN Company ON Company.companyID = Order.companyID
GROUP By Company, Year
Any ideas?

Not sure what RDMS you are using but this should do the trick. The datepart and dateadd stuff are tsql specific but I'd assume you'd have access to similar functions on whatever platform you are using. The case in the where determines which year value to use.
Answer:
select c.companyid
,yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,1,o.orderdate))) as yearending
,sum(ordervalue) as numberoforders
from #orders o
join #companies c
on o.companyid = c.companyid
where orderdate between case when (cast(yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate)) as datetime) >= o.orderdate)
then yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,-1,o.orderdate)))
else yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate))
end
and
case when (cast(yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate)) as datetime) >= o.orderdate)
then yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate))
else yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,1,o.orderdate)))
end
group by c.companyid, o.orderdate, yearendingdate
Code to figure out problem:
declare #orders table (OrderDate datetime
,CompanyID varchar(20)
,OrderValue int)
insert into #orders
values (getdate(),'MS',2)
insert into #orders
values (DateAdd(year, -1, getdate()),'MS',3)
insert into #orders
values (DateAdd(year, -1, getdate()),'MS',1)
insert into #orders
values (DateAdd(year, 1, getdate()),'MS',4)
insert into #orders
values (DateAdd(year, 1, getdate()),'Blizzard',2)
insert into #orders
values (getdate(),'MS',11)
declare #companies table (CompanyID varchar(20)
,YearEndingDate varchar(20))
insert into #companies
values ('MS', '05/6')
insert into #companies
values ('Blizzard', '07/01')
select c.companyid
,o.orderdate
,yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate)) as sameyear
,yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,1,o.orderdate))) as plusyear
,yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,-1,o.orderdate))) as minusyear
from #orders o
join #companies c
on o.companyid = c.companyid
select c.companyid
,yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,1,o.orderdate))) as yearending
,sum(ordervalue) as numberoforders
from #orders o
join #companies c
on o.companyid = c.companyid
where orderdate between case when (cast(yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate)) as datetime) >= o.orderdate)
then yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,-1,o.orderdate)))
else yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate))
end
and
case when (cast(yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate)) as datetime) >= o.orderdate)
then yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate))
else yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,1,o.orderdate)))
end
group by c.companyid, o.orderdate, yearendingdate

Related

How do you update Year field in the datetime column using another datetime column?

I have two columns (Birth_date and Purchase_date) and would like to create a column (Birth_date_update) using following conditions
Conditions:
When Birth_date is later than Purchase_date, take birth_date.
When Birth_date is earlier than Purchase_date, Birth_date_update will take the year from purchase_date and override year from birth_date.
If the final value from condition 2 is still earlier than purchase_date, than find next birth_date anniversary that is bigger than purchase date.
Note: Condition 2 and 3 can be summarized as find earliest anniversary of birth_date greater than purchase_date.
Birth_date purchase_date Birth_date_update
2002-02-21 2006-05-11 2007-02-21
2004-01-18 2004-01-25 2005-01-18
2011-07-24 2011-04-09 2011-07-24
2006-12-16 2007-10-08 2007-12-16
2007-04-30 2008-03-14 2008-04-30
I have no idea how to code this.. please help!
update my_table
set birth_date_update = case
when birth_date > purchase_date then birth_date -- Condition 1
when birth_date < purchase_date then dateadd(year, datediff(year, birth_date, purchase_date), birth_date) -- Condition 2
when dateadd(year, datediff(year, birth_date, purchase_date), purchase_date) < purchase_date
then dateadd(year, 1, dateadd(year, datediff(year, birth_date, purchase_date), purchase_date)) end -- Condition 3
Result from above answer doesn't seem to be correct. Looks like Condition 3 is not working consistent. So I added my answer
create table TAB1 (BD date, PD date, BDU date)
insert into TAB1 values
('2002-02-21', '2006-05-11', NULL),
('2004-01-18', '2004-01-25', NULL),
('2011-07-24', '2011-04-09', NULL),
('2006-12-16', '2007-10-08', NULL),
('2007-04-30', '2008-03-14', NULL)
;with cc as (
select BD, PD,
case
when BD > PD then BD
when BD < PD then cast(cast(year(PD) as varchar) + '-' + cast(month(BD) as varchar) + '-' + cast(day(BD) as varchar) as date)
end as BDU
from TAB1
)
, cc2 as (
select BD, PD,
case
when BDU < PD then dateadd(day, 365, BDU)
else BDU
end as BDU
from cc
)
update T1
set BDU = cc2.BDU
from TAB1 T1
inner join cc2 on cc2.BD = T1.BD and cc2.PD = T1.PD
select * from TAB1
I do not want to be left out of this one. Here is my answer
UPDATE dbo.BirthDateTable SET Birth_date_update =
CASE WHEN Birth_date >= purchase_date THEN Birth_date -- Condition 1
WHEN Birth_date < purchase_date
THEN CASE
WHEN CONVERT(Date , CAST( DATEPART(YEAR,purchase_date) AS Varchar(4)) + '-' + CAST(DATEPART(MONTH,Birth_date) AS Varchar(2)) + '-' + CAST(DATEPART(DAY, Birth_date) AS Varchar(2))) > purchase_date
THEN CONVERT(Date , CAST( DATEPART(YEAR,purchase_date) AS Varchar(4)) + '-' + CAST(DATEPART(MONTH,Birth_date) AS Varchar(2)) + '-' + CAST(DATEPART(DAY, Birth_date) AS Varchar(2))) -- Condition 2
ELSE DATEADD(YEAR,1,CONVERT(Date , CAST( DATEPART(YEAR,purchase_date ) AS Varchar(4)) + '-' + CAST(DATEPART(MONTH,Birth_date) AS Varchar(2)) + '-' + CAST(DATEPART(DAY, Birth_date) AS Varchar(2)))) -- Condition 3
END
END
Here is a select example.
SELECT
CASE WHEN Birth_date >= purchase_date THEN Birth_date -- Condition 1
WHEN Birth_date < purchase_date
THEN CASE
WHEN CONVERT(Date , CAST( DATEPART(YEAR,purchase_date) AS Varchar(4)) + '-' + CAST(DATEPART(MONTH,Birth_date) AS Varchar(2)) + '-' + CAST(DATEPART(DAY, Birth_date) AS Varchar(2))) > purchase_date
THEN CONVERT(Date , CAST( DATEPART(YEAR,purchase_date) AS Varchar(4)) + '-' + CAST(DATEPART(MONTH,Birth_date) AS Varchar(2)) + '-' + CAST(DATEPART(DAY, Birth_date) AS Varchar(2))) -- Condition 2
ELSE DATEADD(YEAR,1,CONVERT(Date , CAST( DATEPART(YEAR,purchase_date ) AS Varchar(4)) + '-' + CAST(DATEPART(MONTH,Birth_date) AS Varchar(2)) + '-' + CAST(DATEPART(DAY, Birth_date) AS Varchar(2)))) -- Condition 3
END
END
FROM dbo.BirthDateTable
Other post about above answer not being correct was written when the order of the answers was different on the page. I believe this answer meets the criteria.#JamieHong, could you see if this select works on your system? I padded the month and day with zeros.
SELECT
CASE WHEN Birth_date >= purchase_date THEN Birth_date
WHEN Birth_date < purchase_date
THEN CASE
WHEN CONVERT(Date , CAST( DATEPART(YEAR,purchase_date) AS Varchar(4)) + '-' + RIGHT('00' + CAST(DATEPART(MONTH,Birth_date) AS Varchar(2)),2) + '-' + RIGHT('00' + CAST(DATEPART(DAY, Birth_date) AS Varchar(2)),2)) > purchase_date
THEN CONVERT(Date , CAST( DATEPART(YEAR,purchase_date) AS Varchar(4)) + '-' + RIGHT('00' + CAST(DATEPART(MONTH,Birth_date) AS Varchar(2)),2) + '-' + RIGHT('00' + CAST(DATEPART(DAY, Birth_date) AS Varchar(2)),2))
ELSE DATEADD(YEAR,1,CONVERT(Date , CAST( DATEPART(YEAR,purchase_date ) AS Varchar(4)) + '-' + RIGHT('00' + CAST(DATEPART(MONTH,Birth_date) AS Varchar(2)),2) + '-' + RIGHT('00' + CAST(DATEPART(DAY, Birth_date) AS Varchar(2)),2)))
END
END AS CalcDate
FROM dbo.BirthDateTable

SQL - Run second Query if count result = 0

Both my SELECT queries work below and return values with as two separate results. What I would like to do is if the first SELECT statement returns a 0 and it will sometimes due to the nature of our work, I would like the second to run ignoring the first one that returns zero if possible. IF the first one returns a result greater than zero then I do not want the second to run.
I have been all over looking and tried different IF ELSE and such but because of the specific date/time formulas used I am thinking it may not be possible or I this may have to be re-written altogether. There is a purpose for this but I will not bore you. Thanks in advance!
Declare #StartDate as DateTime
Declare #EndDate as DateTime
Declare #TodaysDate as DateTime
Declare #Previous as DateTime
Declare #Previous2 as DateTime
set #TodaysDate = GETDATE()
set #Previous = DATEADD(day,-1,#TodaysDate)
set #Previous2 = DATEADD(day,-2,#TodaysDate)
-- SELECT Statetment one starts here
set #StartDate = cast(convert(varchar(4), datepart(yyyy, getdate())) + '-' +
convert(varchar(2), datepart(mm, #Previous)) + '-' +
convert(varchar(2), datepart(dd, #Previous)) + ' ' +
'05:00' as datetime)
set #EndDate = cast(convert(varchar(4), datepart(yyyy, getdate())) + '-' +
convert(varchar(2), datepart(mm, #Previous)) + '-' +
convert(varchar(2), datepart(dd, #Previous)) + ' ' +
'16:59' as datetime)
SELECT Count(*) as FirstShfitPrevious
FROM [TOL_PROD_DB].[dbo].[tblLOT_CTRL_Active_Component]
WHERE Close_Time_Stamp between #StartDate and #EndDate
-- Query 2 Starts, Declarations already made at beginning
set #StartDate = cast(convert(varchar(4), datepart(yyyy, getdate())) + '-' +
convert(varchar(2), datepart(mm, #Previous2)) + '-' +
convert(varchar(2), datepart(dd, #Previous2)) + ' ' +
'05:00' as datetime)
set #EndDate = cast(convert(varchar(4), datepart(yyyy, getdate())) + '-' +
convert(varchar(2), datepart(mm, #Previous2)) + '-' +
convert(varchar(2), datepart(dd, #Previous2)) + ' ' +
'16:59' as datetime)
SELECT Count(*) as FirstShfitPrevious2
FROM [TOL_PROD_DB].[dbo].[tblLOT_CTRL_Active_Component]
WHERE Close_Time_Stamp between #StartDate and #EndDate
You can try to store the value of your first query result in a variable and then then check the value like
declare #myVar int
SELECT #myVar = Count(*) as FirstShfitPrevious
FROM [TOL_PROD_DB].[dbo].[tblLOT_CTRL_Active_Component]
WHERE Close_Time_Stamp between #StartDate and #EndDate)
if(#myVar = 0)
//Here your second query logic
begin
set #StartDate = cast(convert(varchar(4), datepart(yyyy, getdate())) + '-' +
convert(varchar(2), datepart(mm, #Previous2)) + '-' +
convert(varchar(2), datepart(dd, #Previous2)) + ' ' +
'05:00' as datetime)
set #EndDate = cast(convert(varchar(4), datepart(yyyy, getdate())) + '-' +
convert(varchar(2), datepart(mm, #Previous2)) + '-' +
convert(varchar(2), datepart(dd, #Previous2)) + ' ' +
'16:59' as datetime)
SELECT Count(*) as FirstShfitPrevious2
FROM [TOL_PROD_DB].[dbo].[tblLOT_CTRL_Active_Component]
WHERE Close_Time_Stamp between #StartDate and #EndDate
end
use NOT Exists..
if NOT Exists
(Select 1 as FirstShfitPrevious--first query
FROM [TOL_PROD_DB].[dbo].[tblLOT_CTRL_Active_Component]
WHERE Close_Time_Stamp between #StartDate and #EndDate
)
Begin
SELECT Count(*) as FirstShfitPrevious2--second query
FROM [TOL_PROD_DB].[dbo].[tblLOT_CTRL_Active_Component]
WHERE Close_Time_Stamp between #StartDate and #EndDate
END
Else
Begin
--First query
End
or even that way:
SELECT TOP 1 Count(*) as FirstShfitPrevious2
FROM [TOL_PROD_DB].[dbo].[tblLOT_CTRL_Active_Component]
WHERE Close_Time_Stamp between #StartDate and #EndDate
GROUP BY CAST(Close_Time_Stamp AS DATE)
ORDER BY CAST(Close_Time_Stamp AS DATE) DESC
with period covering both date ranges.

Combining two rows in one select query

Hi I am having a hard time combining two records (from a single table) on a single query. The idea is, DATE_FIELD column is a date type and ColA is an integer data type.
To further illustrate my inquiry, I have attached an image below
1.) Is the raw table.
2.) Is the desired output.
P.S. The filter for DATE_FIELD is not a simple "WHERE DATE_FIELD IN" clause.
For example, I wanted to get the DATE_FIELD=12/30/2013. Then I need to get the Previous Sept DATE_FIELD also, which is 9/30/2013 programatically by using this query that I got from the web:
CASE
WHEN MONTH(DATE_FIELD) < 10
THEN
(cast(CAST((DATE_FIELD) - 1) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
ELSE
( cast(CAST((YEAR(DATE_FIELD)) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
END
Here is my current sql script (which cannot get the ColA equivalent for Previous Sept filter:
SELECT DATE_FIELD, ColA,
CASE
WHEN MONTH(DATE_FIELD) < 10
THEN
(cast(CAST((YEAR(DATE_FIELD) - 1) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
ELSE
( cast(CAST((YEAR(DATE_FIELD)) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
END AS PREVIOUS,
(
SELECT ColA
FROM TABLE_A
WHERE DATE_FIELD =
CASE
WHEN MONTH(DATE_FIELD) < 10
THEN
(cast(CAST((YEAR(DATE_FIELD) - 1) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
ELSE
( cast(CAST((YEAR(DATE_FIELD)) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
END
) AS PYE_colA
FROM TABLE_A
WHERE DATE_FIELD = '12/30/2013'
Thanks!
Do a cross join with the same table and use your CASE structure only in the where clause:
SELECT a.DATE_FIELD AS DATE_FIELD_1,
a.ColA AS ColA_1,
b.DATE_FIELD AS DATE_FIELD_2,
b.ColA AS ColA_2
FROM TABLE_A a
CROSS JOIN TABLE_A b
WHERE DATE_FIELD_1 = 'your date'
AND DATE_FIELD_2 = (
CASE
WHEN MONTH(DATE_FIELD_1) < 10
THEN
(cast(CAST((YEAR(DATE_FIELD_1) - 1) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
ELSE
( cast(CAST((YEAR(DATE_FIELD_1)) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
END)
;
Another possibility based on Thorsten Kettners remarks:
SELECT a.DATE_FIELD AS DATE_FIELD_1,
a.ColA AS ColA_1,
b.DATE_FIELD AS DATE_FIELD_2,
b.ColA AS ColA_2
FROM TABLE_A a
INNER JOIN TABLE_A b
ON b.DATE_FIELD = (
CASE
WHEN MONTH(a.DATE_FIELD) < 10
THEN
(cast(CAST((YEAR(a.DATE_FIELD) - 1) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
ELSE
( cast(CAST((YEAR(a.DATE_FIELD)) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
END)
WHERE a.DATE_FIELD = 'your date'
;

Dynamic dates in SQL Server SQL statement

Thanks in advance for any help on this one.
Say I have a query that compares data across years, starting at some arbitrary year and never ending (going into the future), for the same period each year up to the last completed month (which has the characteristic that Jan data never shows until Feb 1). Say also, that one cannot use T-SQL. Is there a way to reformulate the following query to generate the dates dynamically starting from 2008/01/01 (or even just doing it for all years) and going forever without any hardcoding?
select
case
when oact.fathernum like '112%' then sum(jdt1.debit) - sum(jdt1.credit)
end as [Accounts Receivable],
jdt1.refdate as [Posting Date]
from jdt1
inner join oact on jdt1.account = oact.AcctCode
where (oact.fathernum like '1%')
and
(jdt1.refdate between '2008/01/01' and dateadd(day, -1, '2008/' + cast(month(getdate()) as varchar(2)) + '/01')
or jdt1.refdate between '2009/01/01' and dateadd(day, -1, '2009/' + cast(month(getdate()) as varchar(2)) + '/01')
or jdt1.refdate between '2010/01/01' and dateadd(day, -1, '2010/' + cast(month(getdate()) as varchar(2)) + '/01')
or jdt1.refdate between '2011/01/01' and dateadd(day, -1, '2011/' + cast(month(getdate()) as varchar(2)) + '/01')
or jdt1.refdate between '2012/01/01' and dateadd(day, -1, '2012/' + cast(month(getdate()) as varchar(2)) + '/01')
or jdt1.refdate between '2013/01/01' and dateadd(day, -1, '2013/' + cast(month(getdate()) as varchar(2)) + '/01')
or jdt1.refdate between '2014/01/01' and dateadd(day, -1, '2014/' + cast(month(getdate()) as varchar(2)) + '/01')
or jdt1.refdate between '2015/01/01' and dateadd(day, -1, '2015/' + cast(month(getdate()) as varchar(2)) + '/01')
or jdt1.refdate between '2016/01/01' and dateadd(day, -1, '2016/' + cast(month(getdate()) as varchar(2)) + '/01')
or jdt1.refdate between '2017/01/01' and dateadd(day, -1, '2017/' + cast(month(getdate()) as varchar(2)) + '/01'))
group by oact.fathernum, jdt1.refdate
Failing that, any one care to try their hand at a reformulation using T-SQL in a stored procedure that solves the problem? The date upper bound could always be the current year as long as it is dynamic.
The TSQL below shows a method of building a dynamic calendar table.
The query as shown changes the pivot date with each year, but further on is shown how you can fix the calendar 'start' date at a particular year.
select
case
when oact.fathernum like '112%' then sum(jdt1.debit) - sum(jdt1.credit)
end as [Accounts Receivable],
jdt1.refdate as [Posting Date]
from jdt1
inner join oact on jdt1.account = oact.AcctCode
inner join (select
FirstDayOfYear =DATEADD(m,datediff(m,0,getdate())-MONTH(getdate())+1,0),
FirstDayOfMonth =DATEADD(m,datediff(m,0,getdate()),0)) D
inner join master..spt_values v on v.type='P'
and v.number between 0 and 500 -- is 500 years enough? max=2047 from this table
on jdt1.refdate >= DATEADD(year,v.number,D.FirstDayOfYear)
and jdt1.refdate < DATEADD(year,v.number,D.FirstDayOfMonth)
where (oact.fathernum like '1%')
group by oact.fathernum, jdt1.refdate
The select creates a single record of 2 pivot dates, as named
inner join (select
FirstDayOfYear =DATEADD(m,datediff(m,0,getdate())-MONTH(getdate())+1,0),
FirstDayOfMonth =DATEADD(m,datediff(m,0,getdate()),0)) D
The 2 pivot dates are the first day of the **current year**, and the first day of the current month (also in the current year). If you need the first day of a **specific** year and the first day of month (current month) but in the same specific year, you can use the variation below (example for 2008-Jan-01)
select
FirstDayOfYear =cast('20080101' as datetime),
FirstDayOfMonth =dateadd(m,month(getdate())-1,'20080101')
This uses the pivot dates and the built-in number sequence to progressively add 1 year each time to the pivot dates, starting at adding 0 (for current year).
inner join master..spt_values v on v.type='P'
and v.number between 0 and 500
on jdt1.refdate >= DATEADD(year,v.number,D.FirstDayOfYear)
and jdt1.refdate < DATEADD(year,v.number,D.FirstDayOfMonth)
Notice also that instead of
date between A and B
I normally prefer
date >= A and date < B+1
Which works whether or not B includes time information. It doesn't matter for your query, but is good practice for consistence.
Start with a numbers table to generate datesets and join on it
This SO question does it for day sequences
Would somethign like this work?:
YEAR(jdt1.refdate) between 2008 and 2017
and
MONTH(jdt1.refdate) < MONTH(getdate())
If you are using SQL Server 2005+, you can simply build your calendar on the fly:
With MaxDate As
(
Select Max(refdate) As [Date]
From jdt1
)
, Calendar As
(
Select Cast( Cast(Year(GetDate())As char(4)) + '0101' As datetime ) As [StartDay]
, DateAdd(d, -1, Cast( Cast(Year(GetDate()) + 1 As char(4)) + '0101' As datetime ) )As [EndDay]
Union All
Select DateAdd(yyyy, 1, [StartDay])
, DateAdd(yyyy, 1, [EndDay])
From Calendar
Join MaxDate
On Year(DateAdd(yyyy, 1, [EndDay])) <= Year(MaxDate.[Date])
)
Select ...
From Calendar As C
Join jdt1
On jdt1.refdate Between C.StartDay And C.EndDay
Join oact
On oact.AcctCode = jdt1.account
Where oct.fathernum Like '%1'
Group By oact.fathernum, jdt1.refdate
Option ( MaxRecursion 0 );
In this solution, I started with today's Year and expanded out to the Year of the last refdate.

Getting date string from getdate method

I need date string using sql statement like..
select getDate()
this will return 2010-06-08 16:31:47.667
but I need in this format 201006081631 = yyyymmddhoursmin
How can I get this?
Thanks
One way
select left(replace(replace(replace(
convert(varchar(30),getDate(),120),' ',''),'-',''),':',''),12)
or like this
select replace(replace(replace(
convert(varchar(16),getDate(),120),' ',''),'-',''),':','')
or
select convert(varchar(8), getdate(),112) +
(replace(convert(varchar(5), getdate(),108),':',''))
See also: CAST and CONVERT (Transact-SQL)
Another way...
DECLARE #d DATETIME
SELECT #d = '2010-06-09 1:37:58.030'
Select Convert(BigInt, 100000000) * Year(#d)
+ Month(#d) * 1000000
+ Day(#d) * 10000
+ DatePart(Hour, #d) * 100
+ DatePart(Minute, #d)
The returned data type here is a BigInt.
Using DATEPART:
SELECT CAST(DATEPART(yyyy, x.dt) AS VARCHAR(4)) +
CASE WHEN DATEPART(mm, x.dt) < 10 THEN '0'+ CAST(DATEPART(mm, x.dt) AS VARCHAR(1)) ELSE CAST(DATEPART(mm, x.dt) AS VARCHAR(2)) END +
CASE WHEN DATEPART(dd, x.dt) < 10 THEN '0'+ CAST(DATEPART(dd, x.dt) AS VARCHAR(1)) ELSE CAST(DATEPART(dd, x.dt) AS VARCHAR(2)) END +
CASE WHEN DATEPART(hh, x.dt) < 10 THEN '0'+ CAST(DATEPART(hh, x.dt) AS VARCHAR(1)) ELSE CAST(DATEPART(hh, x.dt) AS VARCHAR(2)) END +
CASE WHEN DATEPART(mi, x.dt) < 10 THEN '0'+ CAST(DATEPART(mi, x.dt) AS VARCHAR(1)) ELSE CAST(DATEPART(mi, x.dt) AS VARCHAR(2)) END
FROM (SELECT '2010-06-08 16:31:47.667' dt) x
For SQL Server 2005+, I'd look at creating a CLR function for format a date -- the C# DateTime.ToString() supports providing a more normal means of formatting the date.