I m trying to dig more in the SQL query , I'm with it.
Yearmo Back_1_month
------- ------------
201202 201201 Where 201202 is Feb 2012 , 201201 is Jan 2012
201201 201112
201204 201203
201212 201211
I m confused , how can make it for 201201.
Assuming that yearmo is an int:
DECLARE #Yearmo INT
SET #Yearmo = 201201
-- First, convert yearmo to a varchar.
-- Next, add a "day" portion to the varchar.
-- Then, convert to a date.
-- Then, subtract a month.
-- Finally, convert back to your original format using char(6).
SELECT CONVERT(
CHAR(6),
(DATEADD(MONTH, -1, CAST(CAST(#YearMo AS VARCHAR) + '01' AS DATETIME))),
112
)
This works in one single sql query :
SELECT CONVERT(VARCHAR(6), DATEADD(month, -1 , convert(datetime, CAST ( 201201 AS VARCHAR(8)) + '01', 112) ) , 112)
To substract a month, you can use DATEADD like this
SELECT DATEADD(month, -1, yearmo)
But then you will need to format your date and you might need to cast yearmo as a datetime if it's not.
Try this:
SELECT yearmo,
LEFT(CONVERT(CHAR(8), DATEADD(month, -1, CONVERT(datetime, yearmo + '01')), 112), 6)
FROM <YOUR_TABLE>
SQL Fiddle
You can create a Stored Procedure with argument as yearmo and then save substring(yr) and substring(mo) in two variables and then see, if substring(mo) is 01 then decrement substring(yr) after casting and change substring(mo) to 12 and then append both substring and return.
Related
IF I Select #rpmMonth = SEP 2019 it should pull the data from JAN 2019 to SEP 2019
**I Have only One Parameter Value i.e #rpmMonth of VARCHAR Type.
Declare #firstDay Date=(
select convert(varchar(10),DATEADD(Year,-1*DateDiff(Year,getdate(),0),0),120))
Declare #CurDate Date=(
SELECT convert(varchar(10),DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0)),120))
select * from YOURTABLE
where colname between #firstDay and #CurDate
Ideally, you should be using a date datatype, not a varchar. If we do, however, have to use a varchar then you could do something like this:
SELECT {Columns}
FROM {Your Schema And Table}
WHERE {DateColumn} >= CONVERT(date,CONCAT(RIGHT(#rpmMonth),'0101'))
AND {DateColumn} < DATEADD(MONTH, 1, CONVERT(date, '01 ' + #rpmMonth));
(Obviously replace the parts in braces ({}) and assumes the language of the LOGIN is an English based language.)
This would give you all rows on or after Jan 01 of the year for #rpmMonth and before the month after #rpmMonth.
If you use a proper date, and pass the first date of the month i.e. (2019-09-01 for the sample you gave), then you could do the below:
SELECT {Columns}
FROM {Your Schema And Table}
WHERE {DateColumn} >= DATEADD(YEAR, DATEDIFF(YEAR, 0, #rpmMonth),0)
AND {DateColumn} < DATEADD(MONTH, 1, #rpmMonth);
SQL Server is pretty good about converting date values. You should be able to do:
select . . .
from t cross join
(values (convert(date, #rpmMonth)) as v(dte)
where datecol >= datefromparts(year(v.dte), 1, 1) and
datecol < datefromparts(year(dateadd(month, 1, v.dte)), month(dateadd(month, 1, v.dte)), 1)
I have a field in my database table called Month which holds its values as an INT it has the values 1 to 12 - I would like a way to convert 1 to read 1-11-2016 00:00:00 ie as a datetime field, 2 to read 1-12-2016 00:00:00, 3 to read 1-1-2017 00:00:00 - how can I convert a value like this? I am ok with doing case to switch but the convert/cast is confusing me...
You need to define a startdate (either by parameter or in a CTE), then just use dateadd()
#StartDate = '2016-10-01 00:00:00'
select dateadd(mm, t1.month, #StartDate) as NewMonth
from MyTable t1
Another response is
SELECT CONVERT(DATE, '2016-' + CAST(id AS VARCHAR(2)) + '-01') AS myDate
FROM T1
But y prefer JohmHC answer !!
I have a query built on the msdb..sysjobhistory table the MSDB database of my SQL Server. I want to be able to only give me back the stuff with the previous date. (in this example, 1/14/2015 would be yesterday) How do I go about this when the run_date information is in YYYYMMDD Integer format?
SELECT server
, jh.run_date
, jh.run_time
, j.name
, jh.run_duration
, jh.step_name
, run_status
, message
FROM msdb..sysjobhistory jh
INNER JOIN msdb..sysjobs j ON jh.job_id = j.job_id
WHERE jh.step_id = 0
Please advise.
-Nick
You could try converting that INT first to a VARCHAR and then using the 112 "Style" (noted on the MSDN page for Cast and Convert), convert that to a real DATETIME. For example:
SELECT CONVERT(DATETIME, CONVERT(VARCHAR(10), 20150115), 112)
Of course, doing that alone would invalidate an index on the [run_date] field, if there is one. If that is the case, then you can just do the DATEADD to substract a day and then convert back to VARCHAR and then to INT. For example:
SELECT CONVERT(INT,
CONVERT(VARCHAR(10),
DATEADD(DAY,
-1,
CONVERT(DATETIME, CONVERT(VARCHAR(10), 20150115), 112)
),
112
)
);
On my SQL Server 2012 instance there is no index on [run_date], but might be best to still not wrap a field around a function.
If just using a DATETIME value, such as provided by GETDATE(), it would look like:
WHERE jh.step_id = 0
AND jh.run_date = CONVERT(INT,
CONVERT(VARCHAR(10),
DATEADD(DAY, -1, GETDATE()),
112)
)
I have the following column, date_period2 in my query which displays date in yyyy-mm format but as a string.
date_period2
201304
201305
201306
201307
How can i convert that to a DATE format so I can use it to get the working days of the specific month. So for example, 201304 would be converted to 04-2013 as a DATE instead of a string.
This is my query which is calculating an expression based on the date_period2 field and it's not working because it's a string format:
SELECT TOP 1000 [date_period2]
,[amount]
,[amount]/(SELECT 20 + COUNT(*) FROM
(SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, [date_period2]), 28) AS theDate
UNION
SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, [date_period2]), 29)
UNION
SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, [date_period2]), 30) ) AS d
WHERE DATEPART(DAY, [date_period2]) > 28 AND DATEDIFF(DAY, 0, [date_period2]) % 7 < 5) AS [Weekly Charge]
FROM [database].[dbo].[table]
The issue is the amount is being divided by 20 and not by the working days for the month-year.
Example:
date_period2 amount charge average (amount/total working days of the month)
201304 1750359.95 87517.9975
So according to the result above the charge average is supposed to be 1750359.95/22, but instead it is being divided by 20 giving it the wrong output.
How can I either edit the query or convert the date to ensure the output is done correctly?
Just put the string in an unambiguous date format like yyyy-mm-dd:
SELECT
CONVERT(DATETIME,
SUBSTRING(date_period2,1,4) + '-'
+ SUBSTRING(date_period2,5,2) + '-01')
That will convert 201304 into 2013-04-01 which will convert directly to a DateTime.
EDIT
Since your source column is actually an integer column, a cleaner method is:
select CONVERT(DATETIME,CONVERT(CHAR(6),date_period2)+'01')
that will convert 201304 to "20130401" whihc is still unambiguous to the datetime parser.
You can convert date_period2 to a datetime data type with following logic.
Please change as per your need.
declare #i int
select #i = CONCAT('201305','01')
select CONVERT (datetime,convert(char(8),#i))
In CONCAT('201305','01') '01' will be constant, only '201305' will change.
201404 can converted into 04-2014
declare #x VARCHAR(20)
SET #x = convert(varchar(7), getdate(), 126)
select SUBSTRING(#x,6,CHARINDEX('-',#x)) +'-'+SUBSTRING(#x,0,CHARINDEX('-',#x))
I have a simple table structure, where my DATE column has yyyy-mm-dd format. I'd like to split all the dates and INSERT them in to my time dimension table, that contains day, month, quarter and year columns. I'm not sure how to get going with this (trying with query as insert into).
EXAMPLE: SPLIT 2010-03-01 AND INSERT 2010 into year column, 03 into month column, 01 into day column and 1 into quarter column.
Additionally I'd like to assign the names to specific date part (for example month_name for 1 is January), is it good practice to store date-name values inside same table?
Edit: I've just realized that I probably made big mistake? Is TIME dimension in DATA WAREHOUSE is supposed to store unique data only (for description purposes?)
Typically a time dimension implies time (hours, minutes, seconds) or datetime.
It sounds like you just need a date dimension. Most of the work is already done for you here: http://smehrozalam.wordpress.com/2009/06/09/t-sql-using-common-table-expressions-cte-to-generate-sequences/
If you are still in the design phase of the fact table, I'd recommend going with date rather than the YYYYMMDD ID format in the tutorial for your PK on the dimension. It's a byte cheaper per row and enables date math. Before SQL 2008, the int dateid format made sense. Now that date is available, it's a more appropriate choice.
As for uniqueness, for hierarchies and associated attribute relationships in ssas I'll typically combine the necessary columns to uniquely identify the period. For example:
SELECT
CAST(YEAR(GETDATE()) as char(4)) + ' ' + DATENAME(MONTH,GETDATE()) MonthUniqueName
, CAST(YEAR(GETDATE()) as char(4)) + ' Q' + CAST(DATEPART(QUARTER,GETDATE()) as char(1)) QuarterUniqueName
returns
MonthUniqueName QuarterUniqueName
2013 March 2013 Q1
Is this what you want?
select Datename(yy,yourDateColumn) as year, Datename(quarter,yourDateColumn), Datename(month, yourDateColumn),Datename(day, yourDatecolumn),CONVERT(varchar(3), yourDateColumn, 100) from yourTable
Assuming you have column type as DateTime
Insert into yourTable (yearColumn, quarterColumn, monthColumn, dayColumn) values
Datename(yy,yourDateColumn) , Datename(quarter,yourDateColumn), Datename(month, yourDateColumn),Datename(day, yourDatecolumn)
-- First solution: date is stored and day, month, year and quarter are computed
DECLARE #Table1 TABLE (
Dt DATE NOT NULL,
DD AS CONVERT(TINYINT, DATEPART(DAY, Dt)) PERSISTED,
MM AS CONVERT(TINYINT, DATEPART(MONTH, Dt)) PERSISTED,
YYYY AS CONVERT(SMALLINT, DATEPART(YEAR, Dt)) PERSISTED,
QQ AS CONVERT(TINYINT, DATEPART(QUARTER, Dt)) PERSISTED
);
INSERT #Table1
VALUES (GETDATE());
SELECT * FROM #Table1;
-- Second solution: day, month and year are stored and date and quarter are stored
DECLARE #Table2 TABLE (
Dt AS CONVERT(DATE, DATEADD(DAY, DD-1, DATEADD(MONTH, MM-1, DATEADD(YEAR, YYYY-1, CONVERT(DATE, '00010101',112))))) PERSISTED,
DD TINYINT NOT NULL CHECK(DD BETWEEN 1 AND 31),
MM TINYINT NOT NULL CHECK(MM BETWEEN 1 AND 12),
YYYY SMALLINT NOT NULL CHECK(YYYY BETWEEN 1 AND 9999),
QQ AS CONVERT(TINYINT, ((MM-1)/3)+1) PERSISTED
);
INSERT #Table2 (DD, MM, YYYY)
VALUES (9,3,2013);
SELECT * FROM #Table2;
Results:
Dt DD MM YYYY QQ
---------- ---- ---- ------ ----
2013-03-09 9 3 2013 1
Dt DD MM YYYY QQ
---------- ---- ---- ------ ----
2013-03-09 9 3 2013 1