I have a view that I want to use to generate a payroll report.
I want it such that it selects/gets the last 3 months of monthly processed data.
E.g. If today is 15th May 2012 and payroll for May has not been done, I want to get the results for April, March and February only.
My query:
SELECT dbo.[#EIM_PROCESS_DATA].U_Tax_year, dbo.[#EIM_PROCESS_DATA].U_Employee_ID, SUM(dbo.[#EIM_PROCESS_DATA].U_Amount) AS PAYE,
dbo.OADM.CompnyName, dbo.OADM.CompnyAddr, dbo.OADM.TaxIdNum, dbo.OHEM.lastName + ', ' + ISNULL(dbo.OHEM.middleName, '')
+ ' ' + ISNULL(dbo.OHEM.firstName, '') AS EmployeeName, dbo.OHEM.govID, dbo.[#EIM_PROCESS_DATA].U_Process_month
FROM dbo.[#EIM_PROCESS_DATA] INNER JOIN
dbo.OHEM ON dbo.[#EIM_PROCESS_DATA].U_Employee_ID = dbo.OHEM.empID CROSS JOIN
dbo.OADM
WHERE (dbo.[#EIM_PROCESS_DATA].U_PD_code = 'SYS033')
GROUP BY dbo.[#EIM_PROCESS_DATA].U_Tax_year, dbo.[#EIM_PROCESS_DATA].U_Employee_ID, dbo.OADM.CompnyName, dbo.OADM.CompnyAddr, dbo.OADM.TaxIdNum,
dbo.OHEM.lastName, dbo.OHEM.firstName, dbo.OHEM.middleName, dbo.OHEM.govID, dbo.[#EIM_PROCESS_DATA].U_Process_month
The field U_Process_Month stores the name of the months of the year (varchar). Any help?
Here is one option if you want to turn a month name into a datetime:
declare #Month varchar(10) = 'DEC'
declare #Year varchar(4) = '2012'
SELECT CAST(#Month ' ' + #Year AS DATETIME) AS KeyDate
Replace the #Month and #Year variables with your field names, and you have the first step ;-)
For selecting only the last three months, try the HAVING clause, together with a variable #MaxKeydate that indicates the last processed month:
SELECT (...) FROM bla
HAVING KeyDate > DATEADD(month, -3, #MaxKeyDate)
You need to see yourself, if you can determine the value for #MaxKeyDate with a simple
SELECT MAX(CAST(#Month ' ' + #Year AS DATETIME)) FROM bla
or if it is more complicated.
Related
The stored procedure below is suppose to get the OrderCompletionDate year as last year AND and adds a month to current month.
So if I run it in January of 2018, it returns data for February 2017, and in February 2018, it will return the data from March 2017, so on and so forth.
My error:
When we get to December, it looks for month 13, which does not exist. I want it to get the current year's January data in this case. So when we get to December 2018, it should return the January 2018 data.
My question is:
How can I change this stored procedure so it still returns the last year and month +1 data. But when we get to December, it returns data for January of the current year?
CREATE PROCEDURE [dbo].[usp_GetAnniversaryCustomers]
#date DATE
AS
SET NOCOUNT ON
SELECT
CustomerID,
BAN_ADSL_TN,
REPLACE(LandlinePhoneNumber, ',', '') LandlinePhoneNumber,
REPLACE(MobilePhoneNumber, ',', '') MobilePhoneNumber,
FirstName,
LastName,
REPLACE(ServiceAddress, ',', '') ServiceAddress,
ServiceAddressAptNo,
REPLACE(ServiceAddressCity, ',', '') ServiceAddressCity,
ServiceAddressState,
ServiceAddressZip,
OrderCompletionDate = CONVERT(VARCHAR(10), OrderCompletionDate, 101)
FROM
dbo.Customers
WHERE
StatusID = 115 AND
YEAR(OrderCompletionDate) = YEAR(#date) - 1 AND
MONTH(OrderCompletionDate) = MONTH(#date) + 1
ORDER BY
OrderCompletionDate DESC
WHERE
StatusID = 115
AND OrderCompletionDate >= DATEADD(month, -11, #date)
AND OrderCompletionDate < DATEADD(month, -10, #date)
By using DATEADD() all the boundary cases are handled for you.
By using >= startDate AND < endDate you make the use of DATEADD() even simpler.
By putting all the calculations on the right hand side (manipulating the variable, not the table's data) you improve performance and enable use of indexes.
This should work
Create PROCEDURE [dbo].[usp_GetAnniversaryCustomers]
#date DATE
AS
SET NOCOUNT ON
DECLARE #HistoricalDate DATE = DATEADD(month,-11,#date);
DECLARE #HistoricalDateStart DATE = DATEADD(month,DATEDIFF(month,0,#HistoricalDate),0);
DECLARE #HistoricalDateEnd DATE = DATEADD(month,1,#HistoricalDateStart);
SELECT CustomerID,
BAN_ADSL_TN,
REPLACE(LandlinePhoneNumber,',','')LandlinePhoneNumber,
REPLACE(MobilePhoneNumber,',','')MobilePhoneNumber,
FirstName,
LastName,
REPLACE(ServiceAddress,',','')ServiceAddress,
ServiceAddressAptNo,
REPLACE(ServiceAddressCity,',','')ServiceAddressCity,
ServiceAddressState,
ServiceAddressZip,
--MailingAddress,
--MailingAddressAptNo,
--MailingAddressCity,
--MailingAddressState,
--MailingAddressZip,
--LanguageID,
--Customer Service Number
OrderCompletionDate = CONVERT(VARCHAR(10), OrderCompletionDate, 101)
FROM dbo.Customers
WHERE StatusID = 115
AND OrderCompletionDate >= #HistoricalDateStart
AND OrderCompletionDate < #HistoricalDateEnd
ORDER BY OrderCompletionDate DESC
I have a table that has columns reportyear and reportmonth. For reportyear, the column is a vharchar (4) that equals to year 2016 format. For reportmonth, it is a varchar (2) that has a 01, 02, 03, etc. format. I have a data parameter that concatenates the two since our end users want a drop down date. So my parameter is #ReportDate varchar (7).
My problem is for one of my selects in my stored procedure, I need to put a where clause where it goes back a month. So if my parameter equals to '2016-11', I want a where clause where it returns '2016-10'. I have successfully done this using the flowing query:
SUBSTRING(#Reportdate, 1, 4) + '-' + cast(substring(#ReportDate, 6, 7) -1 as varchar(20))
This returns '2016-10' if I pick '2016-11' as any report date parameter.
But upon further thinking, this would not work if my report date is in January because the above query just literally subtract a string value. So if I pick '2016-01', the above query would return '2016-0'.
For Example:
Declare #Reportdate varchar(7) = '2016-01'
Select AsDate = dateadd(MM,-1,#ReportDate+'-01')
,AsSting = left(convert(date,dateadd(MM,-1,#ReportDate+'-01'),101),7)
Returns
AsDate AsSting
2015-12-01 2015-12
You can just use case:
select concat(#ReportYear - 1,
(case when #ReportMonth = '01' then '12'
else right(concat('0', #ReportMonth - 1))
end)
)
SQL Server will treat the strings as ints -- with no conversion errors for your values. concat() then converts them back into strings.
EDIT:
I see, this is backwards. Let's add one to the columns in the table and compare to #Report_Month:
where (reportmonth = 12 and
right(#ReportDate, 2) = '01' and left(#Report_date, 4) = reportyear + 1
) or
(left(#ReportDate, 4) = reportyear and
right(#ReportDate, 2) = reportmonth + 1
)
But after considering this, I think you should use a computed column:
alter table t add reportdate as ( datefromparts(reportyear, reportmonth, 1) );
Then simply do:
where dateadd(month, 1, reportdate) = cast(#reportdate + '01' as date)
Of course, you can do the explicit comparison:
where (dateadd(month, 1, datefromparts(reportyear, reportmonth, 1)) =
cast(#reportdate + '01' as date)
)
Note that both of these assume that #reportdate is a string.
I am having table containing two columns one for month and other for year. Based on these two columns I want all records for that financial year. For eg. if month is 10 and year is 2014 then offcourse its financial year will be FY 01StApr14 - 31stMar15.
How do I write a SQL select query to get all the records which were created between FY 01stApr14-31stMar15 available in that table based on month and year.
M trying below query but getting error messge as 'Incorrect syntax near the keyword 'and'.'
with cte as
(
select id,iono,iomonth,ioyear,
convert(datetime,'01/'+right('00' + convert(varchar(10),iomonth,2),2)
+ '/' +convert(varchar(4),IOyear),103) as FinDate from iodetails where iono=12345
)
select month(findate),* from cte where iono=12345 and
findate between
case
when month(findate)>=4
then convert(datetime,'01/'+'04'+ '/' +convert(varchar(4),IOyear),103) and
convert(datetime,'31/'+ '03' + '/' +convert(varchar(4),IOyear+1),103)
else
convert(datetime,'01/'+'04'+ '/' +convert(varchar(4),IOyear),103) and
convert(datetime,'31/'+ '03' + '/' +convert(varchar(4),IOyear),103)
end
Try this:
SELECT *
FROM tableA
WHERE CAST((CAST(YearCol AS VARCHAR(10)) + (CAST(MonthCol AS VARCHAR(10))) AS INT)
BETWEEN CAST((CASE WHEN #V_Month BETWEEN 4 AND 12 THEN CAST((CAST(#V_Year AS VARCHAR(10)) + '04') AS INT)
WHEN #V_Month BETWEEN 1 AND 3 THEN CAST((CAST(#V_Year - 1 AS VARCHAR(10)) + '04') AS INT)
ELSE ''
END
) AS INT)
AND CAST((CASE WHEN #V_Month BETWEEN 4 AND 12 THEN CAST((CAST(#V_Year + 1 AS VARCHAR(10)) + '03') AS INT)
WHEN #V_Month BETWEEN 1 AND 3 THEN CAST((CAST(#V_Year AS VARCHAR(10)) + '03') AS INT)
ELSE ''
END
) AS INT);
If I understand your requirements correctly, you might try this:
SELECT * FROM mytable
WHERE year(dateadd(q, -1, mydate)) = 2014
This will subtract 1 quarter (3 months) from the value of mydate and extract the year. So 31 Mar 2015 becomes 31 Dec 2014 after the subtraction, which when the year is extracted is 2014.
Oops my apologies, I see that you have two columns, month and year. In that case you might try this:
SELECT * FROM mytable
WHERE year(dateadd(q, -1, cast(cast(mymonth AS char) + '/01/' + cast(myyear AS char) AS datetime))) = 2014
That is probably not the most efficient way of doing it however.
UPDATE per my comments
Here is how you might created a computed column on your table:
ALTER TABLE mytable
ADD mydate AS cast(cast(mymonth AS char) + '/01/' + cast(myyear AS char) AS datetime)
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
I want to know how can I get the year and month into my database. For example, suppose it’s August, 2011. The output that I need is like this: CAB 11 08 001 (CAB + YEAR + MONTH + CURRENT NO. in tracking number. )
This is my SQL:
ALTER PROCEDURE [dbo].[generateTrackNo] AS
Declare #tempYear VARCHAR(5),#tempMonth VARCHAR(5)
Set #tempYear = Year(GetDate())
Set #tempMonth = Month(GetDate())
SELECT 'CAB' + Right(Cast(Year(GetDate()) as varchar(10)),2)+ Right(Cast(Month(GetDate()) as varchar(10)),2) + Right('000000'+ Cast(CurrentNo as varchar(10)), 5) from tblTrackNo where GenYear = #tempYear
--UPDATE tblTrackNo SET CurrentNo = CurrentNo + 1 where GenYear = #tempYear
The output for this is CAB1180035, but I need CAB1108035. I need to put zero(0) 08 like this for the month.
In my table I have only genYear and Current No. Do I need to add another column for MONTH?
It looks like you're making separate columns for YEAR, MONTH, etc.
Most (all?) DBMSs I'm aware of have a Date type. Use it. They put a lot of useful stuff in it, like accepting date inputs in different formats and giving them as output in pretty much any format you can think of.
For example, if you have a DT column of type Date in Oracle, you can output month as
SELECT TO_CHAR(DT, "MM") FROM MYTABLE;
and the month will always be displayed as 2 digits (01, 02, ... 12)
SELECT
'CAB'
+ RIGHT(YEAR(GetDate()),2)
+ RIGHT('0' + CONVERT(VARCHAR, MONTH(GetDate())),2)
+ Right('00000' + Cast(CurrentNo as varchar(10)), 5)
That might work..
Using your method \ logic..
Right('0' + Cast(Month(GetDate()) as varchar(10)),2)