Construct a date from parts in SQL Server 2008 - sql

I am using SQL Server 2008 and trying to form a query that will use a CASEstatement with a date calculation to return one of two dates depending on what day of the month the calculation results in.
The goal is if the calculation (in query below) CURRENT_TIMESTAMP + LEAD_TIME results in a day between the 1st and 15th, then assign the 15th of that month. Otherwise, return the last day of that month.
For example, if CURRENT_TIMESTAMP + LEAD_TIME = 07/12/19, return 07/15/19. If that calculation = 07/16/19, return 07/31/19.
This seems like it would be possible using DATEFROMPARTS but I believe since I am using SQL Server 2008 that function is not defined (that is the error I am returning). Any ideas on a work around?
SQL:
SELECT I.po_number,
I.po_item_number AS 'po_item',
S.orderentry_date,
I.po_req_ship_date,
I.ex_factory_date,
I.del_indicator,
H.po_type,
H.vendor_no,
CASE WHEN DATEPART(dd,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME)) BETWEEN 1 AND 15
THEN DATEFROMPARTS(DATEPART(yyyy,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME),mm,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME),15)
ELSE DATEFROMPARTS(DATEPART(yyyy,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME),mm,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME)+1,0))
END AS 'LT_CALC',
H.po_created_by,
I.comment
FROM rbk_sap_user..vw_po_header H
JOIN rbk_sap_user..vw_po_item I ON H.po_number = I.po_number
JOIN rbk_sap_user..vw_mm_material MM ON I.material = MM.material
JOIN (SELECT order_no,
orderentry_date
FROM asagdwpdx_prod..SimoxOrder1
UNION ALL
SELECT order_no,
orderentry_date
FROM asagdwpdx_prod..SimoxOrder2
UNION ALL
SELECT order_no,
orderentry_date
FROM asagdwpdx_prod..SimoxOrder3
) S ON S.order_no = H.ahag_number
WHERE S.orderentry_date BETWEEN '01/31/2019' AND '02/13/2019'
AND I.del_indicator <> 'L'
AND H.po_type NOT IN ('02','06','10','UB')
AND MM.business_segment_code NOT IN ('420','421','422','424')

You can convert all the parts of the date to VARCHAR and string them together to yyyy-mm-dd format, and then CONVERT toDATETIME.
SELECT
...
CASE WHEN DATEPART(dd,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME)) BETWEEN 1 AND 15
THEN CONVERT(DATETIME, CONVERT(varchar, DATEPART(yyyy,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME)))+ '-' + CONVERT(VARCHAR, DATEPART (mm,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME))) + '-' + CONVERT(VARCHAR, 15))
ELSE DATEADD(DAY, -1, CONVERT(DATETIME, CONVERT(VARCHAR, DATEPART(yyyy,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME)))+ '-' + CONVERT(VARCHAR, DATEPART(mm,CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME)+ 1) + '-' + CONVERT(VARCHAR, 1)))
END AS 'LT_CALC'
...
Note that in the ELSE statement, the logic to get the last day of the month is to go the first day of the following month, and then use the DATEADD function to subtract one day. The SQL Server function EOMONTH , introduced in SQL Server 2012, eliminates the need for that logic.

Try this
SELECT CAST(LEFT(CONVERT(varchar, CURRENT_TIMESTAMP + LEAD_TIME, 103 ),2) as int)
then
CASE WHEN CAST(LEFT(CONVERT(varchar, CURRENT_TIMESTAMP + LEAD_TIME, 103 ),2) as int) < 15 THEN
....
ELSE
....
END

Related

Combining date , month , year columns in SQL Server

DD(10)-MM(05)-YYYY(2013)
I have a table with DATE, MONTH, YEAR in separate columns. How I can combine them into a single column Created date?
Output must be: 10-05-2013 (DD-MM-YYYY format)
SELECT RIGHT('00' + DAY, 2) + '-' + RIGHT('00' + MONTH, 2) + '-' + YEAR AS Date
FROM YourTable
I guess you want have a date field instead of a string. So use TO_DATE() function. You can format date anyway you want later.
TO_DATE(YEAR + '/' + MONTH + '/' + DATE, 'yyyy/mm/dd')
You can do it easily:
SELECT to_char(TO_DATE('10 01 2014', 'DD MM YYYY'),'dd-mm-yyyy') AS MYDATE FROM DUAL
To concatenate columns you just need to use "+" in your select statement
SELECT DATE + '-'+ MONTH + '-'+ YEAR FROM table

SQL Find/Ignore invalid date

I am using SQL Server.
From each row, I take day and month values from the fields c.daybirth,c.monthbirth
and the year from getdate(), and I want to have a field that shows if this date is valid or not (invalid example: 31 February)
I have created this solution:
case day(dateadd(month,c.monthbirth-1,dateadd(day,c.daybirth-1,DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)))) when c.daybirth then 1 else 0 end
which works, but I find it hard to read. Is there a smarter alternative?
In SQL Server 2012+, you can do:
where try_convert(date,
datefromparts(year(getdate()), c.monthbirth, c.daybirth)
) is not null
EDIT:
Amusing. This is better:
where try_convert(date,
cast(year(getdate()) * 10000 + c.monthbirth * 100 + c.daybirth as varchar(255))
) is not null

Need to format char(4) hhmm to time only or text to look like hh:mm in sql

In the script below, How do I convert the column HHMM to HH:MM and
convert it to 12hr clock?
The column is a char(4) and format 0000 - 2359.
Just want time or text with a colon(:), no date.
Please note that I do not want date or seconds. How do I do this?
Thank you for your help!
Select
th.[store] as 'My Store',
---> this column th.hhmm as Time, (I need this to format hh:mm)
emp.[First Name],
td.Type as [Total],
Count(*) as Qty,
Convert(varchar(50),SUM(Amount1),1) AS Amount
Try this. It uses LEFT and RIGHT functions
declare #time char(4)='2359'
select left(convert(varchar(100),cast(concat(left(#time,2),':',right(#time,2)) as time),9),5)+
' '+
right(convert(varchar(100),cast(concat(left(#time,2),':',right(#time,2)) as time),9),2)
SQL Server:
right('00' + cast((cast(substring(th.hhmm, 1, 2) as int) - 1) % 12 + 1 as varchar(2)), 2) +
':' + substring(th.hhmm, 3, 2) +
case when cast(substring(th.hhmm, 1, 2) as int) >= 12 then 'pm' else 'am' end
You can use substr to do this in Oracle.
select substr(th.hhmm,1,2)||':'||substr(th.hhmm,3,2) from t
In SQL Server, you can use substring
select substring(th.hhmm,1,2)+':'+substring(th.hhmm,3,2) from t
Fiddle with sample data
Edit:
select
case when cast(substring(th.hhmm,1,2) as int) < 12 then
case when cast(substring(th.hhmm,1,2) as int) = 0 then
'12'+':'+substring(th.hhmm,3,2)+' AM'
else substring(th.hhmm,1,2)+':'+substring(th.hhmm,3,2)+' AM' end
when cast(substring(th.hhmm,1,2) as int) > 12 then
cast(substring(th.hhmm,1,2)%12 as varchar(2)) +':'+substring(th.hhmm,3,2)+' PM'
when cast(substring(th.hhmm,1,2) as int) = 12 then
substring(th.hhmm,1,2)+':'+substring(th.hhmm,3,2)+' PM'
end

Extract and convert a date from a batch number but the date info does not have the year

I have a scenario where I have a batch number and I need to validate the the date in the batch number is the same as today's date. I can extract the date out of the batch number but the problem is that the portion of the batch number used to indicate the date is "27.03" or "2703". The year is not shown. How do I go about converting it to a date that I can use to validate? PS. I am using SQL Server 2012
Thank you.
Not sure if I can fully answer the question without more info. You can try to construct the DDMM value using the current date from SQL server, then use that in a where clause.
For example, you can get the ISO Standard date (112 = yyyymmdd) using the following. More info here:
select CONVERT(nvarchar(8),getdate(),112)
Then from the above YYYYMMDD date, you can get the DDMM value and use it in a where clause something similar to the following:
DECLARE #ddmmValue CHAR(6)
SET #ddmmValue='%'+ SUBSTRING(CONVERT(nvarchar(8),getdate(),112),5, 2) +
SUBSTRING(CONVERT(nvarchar(8),getdate(),112),7, 2) + '%'
select * from MyTest
where BatchNumber like #ddmmValue
This also depends on what the rest of your batch number looks like.
Maybe you can just take advantage of what you've got and append the year then use the German date format to convert to a date type. I'm assuming you want your dates to be no later than today's date.
select
case
when convert(
date,
batch_num + '.' + cast(year(current_timestamp) as char(4)),
104
) > cast(current_timestamp as date)
then dateadd(
yy,
-1,
convert(
date,
batch_num + '.' + cast(year(current_timestamp) as char(4)),
104
)
)
else
convert(
date,
batch_num + '.' + cast(year(current_timestamp) as char(4)),
104
)
end
...
Or pretty much the equivalent...
select
dateadd(
yy,
case
when convert(
date,
batch_num + '.' + cast(year(current_timestamp) as char(4)),
104
) > cast(current_timestamp as date)
then -1
else 0
end,
convert(
date,
batch_num + '.' + cast(year(current_timestamp) as char(4)),
104
)
)
Or if you're just looking to compare to today's date and handle an optional period between the day and month (after I re-read your question)...
where
cast(
date,
replace(stuff(batch_num, 3, 0, '.'), '..', '.') +
'.' + cast(year(current_timestamp) as char(4)),
104
) = cast(current_timestamp as date)
Thank you. I used a REPLACE statement as follows:
SET BatchDate1 = SUBSTRING(Scan,6,4)
SET DateNow1 = REPLACE(CONVERT(varchar(5),GETDATE(),103),'/','')
IF BatchDate1 <> DateNow1
And yes, the batch code sometimes is "DDMM" or "DD.MM" but it always has a unique starting character that would tell you what the date format is so I validated for this first and then the date. Thanks again.

SQL Server 2008 select data only between month and year

I would like select data between two date, without day
An input example:
start month: 9 , start year: 2011
end month: 3, end year: 2012
I think that there are two way to do this.
The first is convert start month and start year to date like 2011-09-01 and convert last date to 2012-03-31, but this requires calculation of the last day of end month. Obtained these date we can use a BEETWEN function for the WHERE clause (but, is the CONVERT function reliable?)
The second solution is to use the DATEPART function like in the following code:
I try to explain: if end year is equal to the initial year, then month must be between the start and end months; else if the final months is greater than the initial years if different from the initial and final year, I take everything in between; else if the final year, the month must be less than or equal to the final month, if the initial year, month must be greater than or equal to the final month
Can you help me do this in the best way? Is correct, the solution I adopted?
declare #IndDebitoCredito bit,#ProgTributo int,#mi as integer,#ai as integer,#mf as integer,#af as integer,#IDAnagrafica varchar(5)
select #mi = 01,#ai = 2011,#mf = 12,#af = 2011,#IDAnagrafica = 'DELEL',#IndDebitoCredito = 1
select distinct rrd.IDTributo
from TBWH_Delega d
--inner join TBWH_SezioneDelega sd on d.IDDelega = sd.IDDelega
inner join TBWH_Rigo rd on rd.IDDelega = d.IDDelega
inner join TBWH_RataRigo rrd on rrd.IDRigo = rd.IDRigo
where
(
DATEPART(MM,d.DataDelega)<=#mf and
DATEPART(MM,d.DataDelega)>=#mi and
DATEPART(YYYY,d.DataDelega)=#ai and
#af = #ai
)
OR
(
--anno finale magg. anno iniziale
#af > #ai AND
(
( -- delega nell'intervallo
DATEPART(YYYY,d.DataDelega)<#af AND
DATEPART(YYYY,d.DataDelega)>#ai
-- DATEPART(MM,d.DataDelega)>=#mi
)
OR
( -- delega limite destro
DATEPART(YYYY,d.DataDelega)=#af AND
DATEPART(MM,d.DataDelega)<=#mf
)
OR
( -- delega limite sinistro
DATEPART(YYYY,d.DataDelega)=#ai AND
DATEPART(MM,d.DataDelega)>=#mi
)
)
)
GO
Your first solution is almost there, but is more complicated than it needs to be and won't work anyway. It will miss out any rows from the last day of the end month.
You can add one month to the end month and then use BETWEEN on the first of each month. eg.
start month: 9 , start year: 2011
end month: 3, end year: 2012
BETWEEN '2011-09-01' AND '2012-04-01'
or, as JNK points out, this will be better:
DataDelega >= '2011-09-01' AND DataDelega < '2012-04-01'
You'll need to add in some logic to deal with the end month being December, but this looks like the simplest way of doing it.
You are WAY overcomplicating this. You really only need two comparisons:
Is the month and year after or equal to the initial value?
Is the month and year before or equal to the final value?
Try:
SELECT *
FROM MyTable
WHERE Datefield BETWEEN
CAST(#mi as varchar) + '/1/' + CAST(#ai as varchar)
-- first of first month
AND
DATEADD(DAY, -1, (DATEADD(Month, + 1, (CAST(#mf as varchar) + '/1/' + CAST(#af as varchar)))))
-- Last day or final month
SELECT *
FROM Table
WHERE DateField
BETWEEN CONVERT(DATE, CONVERT(CHAR(4), #ai) + RIGHT('00' + CONVERT(VARCHAR(2), #mi), 2) + '01', 112)
AND DATEADD(DD, -1, DATEADD(MM, 1, CONVERT(DATE, CONVERT(CHAR(4), #af) + RIGHT('00' + CONVERT(VARCHAR(2), #mf), 2) + '01', 112)))
Avoid using expressions on the DateField columns, as it makes query not SARGable.
I would use:
WHERE DateToCheck >= --- first day of StartMonth
DATEADD( mm, #StartMonth-1,
DATEADD( yy, #StartYear-2000, '2000-01-01')
)
AND DateToCheck < --- first day of next month (after EndMonth)
DATEADD( mm, #EndMonth,
DATEADD( yy, #EndYear-2000, '2000-01-01')
)
DECLARE #mi INT
, #ai INT
, #mf INT
, #af INT
SELECT #mi = 01
, #ai = 2011
, #mf = 12
, #af = 2011
--local variables to hold dates
DECLARE #i DATETIME
, #f DATETIME
--build strings to represent dates in YYYYMMDD format
--add a month to the #f date
SELECT #i = CONVERT(VARCHAR(4), #ai) + RIGHT('0' + CONVERT(VARCHAR(2), #mi),
2) + '01'
, #f = DATEADD(month, 1,
CONVERT(VARCHAR(4), #af) + RIGHT('0'
+ CONVERT(VARCHAR(2), #mf),
2) + '01')
--select data where date >= #i, and < #f
SELECT *
FROM MyTable
WHERE DateField >= #i
AND DateField < #f