I've created the following stored procedure on sql:
CREATE PROCEDURE Sp_generate_report (#YEAR INT,
#MONTH INT)
AS
DECLARE #CATEGORY VARCHAR(20)
DECLARE #BEGIN_DATE DATE
DECLARE #END_DATE DATE
BEGIN
SELECT #BEGIN_DATE = Cast(( Cast(#YEAR AS VARCHAR) + '-'
+ Cast(#MONTH AS VARCHAR) + '-' + '1' ) AS DATE)
SELECT #END_DATE = Cast(( Cast(#YEAR AS VARCHAR) + '-' +
Cast(#MONTH AS VARCHAR) + '-' + '32' ) AS DATE)
SELECT TOP 1 #CATEGORY = Name
FROM dbo.Profitible_categories(#BEGIN_DATE, #END_DATE)
INSERT INTO dbo.MONTHLY_SUMMARY_REPORTS
VALUES (#CATEGORY)
END
The procedure was created successfully, but when I try to execute it with the following command:
EXECUTE SP_GENERATE_REPORT 2012, 7
I get this error message:
Msg 241, Level 16, State 1, Procedure SP_GENERATE_REPORT, Line 8
Conversion failed when converting date and/or time from character
string.
thanks in advance for the help.
You can calculate the last day of the month without all that nasty string concatenation or trying to guess which month it is and pick the last day.
CREATE PROCEDURE dbo.Sp_generate_report
#YEAR INT,
#MONTH INT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #BEGIN_DATE DATE = DATEADD(MONTH, #MONTH-1, CONVERT(DATE,
CONVERT(CHAR(4), YEAR) + '0101'));
DECLARE #END_DATE DATE = DATEADD(DAY, -1, DATEADD(MONTH, 1, #BEGIN_DATE));
INSERT INTO dbo.MONTHLY_SUMMARY_REPORTS
SELECT TOP (1) Name
FROM dbo.Profitible_categories(#BEGIN_DATE, #END_DATE);
END
GO
Related
I want to create a dyamic procedure which accepts tablename, startdate and enddate
which goes like this `
alter procedure task_date #tablename nvarchar(max), #start as datetime,#end as datetime
as begin
declare #t1 as nvarchar(max)
declare #t2 as nvarchar(max)
set #t1='create table '+#tablename+'_'+#start+'(int id)'
set #t1='create table '+#tablename+'_'+#end+'(int id)'
exec(#t1)
exec(#t2)
end
`
If I pass parameters to my stored procedure like this
`exec task_date name,'21/2/2017','24/2/2016`'
Then it should create two tables as abc_21Feb2017 , abc_22Feb2017, abc_23Feb2017, abc_24Feb2017, Means difference between the dates also should be created as tables along with startdate and enddate with underscore seperation
Note: My code is wrong here, i want the proper code along with correct logic, help me out
You could try following solution:
DECLARE #StartDate DATE = '2017-02-22';
DECLARE #EndDate DATE = '2017-02-24';
DECLARE #SqlStatement NVARCHAR(MAX) = N'';
WITH Num10(Number)
AS (
SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL
SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10
),
Num100(Number)
AS (
SELECT (a.Number - 1)*10 + b.Number FROM Num10 a CROSS JOIN Num10 b
)
SELECT #SqlStatement = #SqlStatement
+ N'CREATE TABLE ' + N'dbo.CocoJamboTable' + N'_' + REPLACE(CONVERT(VARCHAR(25), DATEADD(DAY, n.Number - 1, '2017-02-22'), 106), ' ', '') + N'(INT ID)'
+ CHAR(13) + CHAR(10)
FROM Num100 n
WHERE n.Number <= DATEDIFF(DAY, #StartDate, #EndDate) + 1;
PRINT #SqlStatement
--EXEC sp_executesql #SqlStatement
This will generate and execute(--UNCOMMENT LAST LINE) following script:
CREATE TABLE dbo.CocoJamboStupidNameTable_22Feb2017(ID INT)
CREATE TABLE dbo.CocoJamboStupidNameTable_23Feb2017(ID INT)
CREATE TABLE dbo.CocoJamboStupidNameTable_24Feb2017(ID INT)
Edit 1:
[1] N10 and N100 CTEs returns all numbers between 1 and 10 or 1 and 100.
These CTEs could be replaced with a table with numbers. An example of such table can be found here.
[2] Main SELECT statement returns numbers (starting with 1) from N100 CTE or from number table.
[3] DATEDIFF(DAY, #StartDate, #EndDate) + 1 compute number of days between #StartDate and #EndDate including (+1) last one (#EndDate). For example, number of days between 2017-02-22 and 2017-02-24 isn't 2 (24 - 22) but 2 + 1 = 3 (if we take into account 22 but also 24).
[4] WHERE n.Number <= DATEDIFF(DAY, #StartDate, #EndDate) + 1; filter all numbers between 1 and number of days (= difference between start date and end date).
[5] SELECT DATEADD(DAY, n.Number - 1, '2017-02-22') compute all dates between start date and also end date: 2017-02-22, 23, 24.
[6] SELECT N'CREATE TABLE .... DATEADD(DAY, n.Number, ... will generate the SQL CREATE TABLE scripts for every date between start date and end date.
A simple while loop with a test on date might suffice
use sandbox
go
drop procedure p
go
CREATE procedure [dbo].[p]
#start date ,
#end date
as
declare #t nvarchar(max)
while #start <= #end
begin
set #t= concat('create table abc_',replace(cast(#start as varchar(10)),'-','_'),char(40), 'id int' ,char(41))
print #t
EXEC sp_executesql #t
set #start = dateadd(d,1,#start)
end
GO
exec dbo.p '2017-06-21','2017-06-25'
select table_name from information_schema.tables where table_name like 'abc%'
Result
table_name
--------------
abc_2017_06_21
abc_2017_06_22
abc_2017_06_23
abc_2017_06_24
abc_2017_06_25
Note the use of ascii characters for left and right parenthesis and the replace to remove illegal - in table name.
GOAL: create a stored procedure that automates this report, so that when execute NameOfStoredProc is run, it does all 3 blocks and returns the query in block 3.
For into table, I want it to be dynamic based on getdate().
(I did not post actual table elements and records, but if needed I can make up something b/c actual data is sensitive)
Database: FY1516
From table: v_all_claim (actually a view)
Into table: March2017_Payments
Here's the code that I execute manually to generate the report.
Block 1:
--creates payment table
SELECT Recipient_ID, DOP, Provider_ID, program_code, poverty_code
INTO FY1516..March2017_Payments
FROM FY1516..v_all_Claim
WHERE amount <> 0
AND DOP BETWEEN '20170301' AND '20170331'
Block 2:
-- add one column to the table created in block 1, sets default value to '' and update to Y
-- if certain constraints are met
ALTER TABLE FY1516..March2017_Payments
ADD TITLE21_Flag varchar(1);
GO
UPDATE FY1516..March2017_Payments
SET TITLE21_Flag = ''
GO
UPDATE FY1516..March2017_Payments
SET TITLE21_Flag = 'Y'
WHERE program_code IN ('A', 'B', 'C')
Block 3 with select statement that gets copied into Excel:
SELECT *
FROM FY1516..March2017_Payments
My attempts thus far:
#start and #end are for between #start and #end
#previousMonth gives first 3 letters of previous month
#previousMonthYear gives the YYYY of the previous month
Hoping #previousMonth +#previousMonthYear +"_Payments" can be the tablename
USE FY1516
CREATE PROCEDURE NameOfStoredProc
AS
DECLARE #start VARCHAR(8), #end VARCHAR(8),
#previousMonth VARCHAR(3), #previousMonthYear VARCHAR(4);
SET #start = CONVERT(VARCHAR(8), DATEADD(MONTH, DATEDIFF(MONHT, 0, GETDATE()) - 1, 0), 112)
SET #end = CONVERT(VARCHAR(8), DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE()) - 1, -1), 112)
SET #previousMonth = LEFT(DATENAME(MONTH, DATEADD(MONTH, -1, GETDATE())), 3)
SET #previousMonthYear = YEAR(DATEADD(MONTH, -1, GETDATE()))
You can combine Block 1 and Block 2 into a single statement:
--creates payment table
Select Recipient_ID
, DOP
, Provider_ID
,program_code
,poverty_code
,TITLE21_Flag = CASE WHEN program_code IN ('A','B','C') THEN 'Y' ELSE '' END
INTO FY1516..March2017_Payments
FROM FY1516..v_all_Claim
WHERE amount <> 0 and DOP between '20170301' and '20170331'
Then, in your proc, you can use dynamic SQL to create your tables. Here's an example:
Create procedure NameOfStoredProc
AS
declare #start varchar(8)
, #end varchar(8)
,#previousMonth varchar(3)
,#previousMonthYear varchar(4);
set #start = convert(varchar(8),dateadd(month, datediff(month,0,getdate())-1,0),112)
set #end = convert(varchar(8),DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE())-1, -1),112)
set #previousMonth = left(datename(month, dateadd(month,-1,getdate())), 3)
set #previousMonthYear = year(dateadd(month,-1,getdate()))
DECLARE #SQLString NVARCHAR(MAX) = 'CREATE TABLE ' + #previousMonth +#previousMonthYear +'_Payments (ColA int)'
EXECUTE sp_executesql #SQLString
You'll want to replace the (ColA int) with your actual column names and data types.
EDIT:
Here's an example that includes Block 1/2 into the stored proc. It checks the existence of the table first, and then runs the appropriate SELECT query.
CREATE PROCEDURE NameOfStoredProc
AS
begin
declare #start varchar(8)
, #end varchar(8)
,#previousMonth varchar(3)
,#previousMonthYear varchar(4);
set #start = convert(varchar(8),dateadd(month, datediff(month,0,getdate())-1,0),112)
set #end = convert(varchar(8),DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE())-1, -1),112)
set #previousMonth = left(datename(month, dateadd(month,-1,getdate())), 3)
set #previousMonthYear = year(dateadd(month,-1,getdate()))
DECLARE #SQLString NVARCHAR(MAX) =
'IF OBJECT_ID('''+#previousMonth +#previousMonthYear +'_Payments'', ''U'') IS NOT NULL
BEGIN
print 1
INSERT INTO FY1516..'+ #previousMonth +#previousMonthYear +'_Payments
Select Recipient_ID
, DOP
, Provider_ID
,program_code
,poverty_code
,TITLE21_Flag = CASE WHEN program_code IN (''A'',''B'',''C'') THEN ''Y'' ELSE '''' END
FROM FY1516..v_all_Claim
WHERE amount <> 0 and DOP between ''20170301'' and ''20170331''
END
ELSE
BEGIN
print 2
Select Recipient_ID
, DOP
, Provider_ID
,program_code
,poverty_code
,TITLE21_Flag = CASE WHEN program_code IN (''A'',''B'',''C'') THEN ''Y'' ELSE '''' END
INTO FY1516..'+ #previousMonth +#previousMonthYear +'_Payments
FROM FY1516..v_all_Claim
WHERE amount <> 0 and DOP between ''20170301'' and ''20170331''
END
'
EXECUTE sp_executesql #SQLString
SET #SQLString = 'SELECT * FROM '+#previousMonth +#previousMonthYear +'_Payments'
EXECUTE sp_executesql #SQLString
END
I have a procedure to fetch data as per the criteria passed. I works fine with #month, #year, #quater.
ALTER PROCEDURE dbo.SPReportTimeSpan
(
#Week int = null,
#Month int = null,
#Year int = null,
#Quater int = null
)
AS
SET NOCOUNT ON
DECLARE #sql nvarchar(4000)
If (#Week) IS NOT NULL
BEGIN
DECLARE #startdate Date, #enddate Date
EXEC dbo.SPReturnStartEndDateOfSpecifiedWeek #Week, #startdate OUTPUT, #enddate OUTPUT
SELECT #startdate, #enddate
END
SELECT #sql='SELECT
CRMDR.Id as Id,.
CRMDR.Request_For_Id as Request_For_Id
From [CRM].[dbo].[CRM_Doctor_Request] AS CRMDR
WHERE CRMDR.Is_Deleted=0 '
If (#Month) IS NOT NULL
SELECT #sql=#sql + ' AND MONTH(CRMDR.Date_Created) like (#Month) '
If (#Year) IS NOT NULL
SELECT #sql=#sql + ' AND YEAR(CRMDR.Date_Created) like (#Year) '
If (#Week) IS NOT NULL
SELECT #sql=#sql + ' AND (CRMDR.Date_Created) BETWEEN (#startdate) AND (#enddate) '
If (#Quater) IS NOT NULL
IF (#Quater = 1)
SELECT #sql=#sql + ' AND MONTH(CRMDR.Date_Created) in (4,5,6) '
IF (#Quater = 2)
SELECT #sql=#sql + ' AND MONTH(CRMDR.Date_Created) in (7,8,9) '
IF (#Quater = 3)
SELECT #sql=#sql + ' AND MONTH(CRMDR.Date_Created) in (10,11,12) '
IF (#Quater = 4)
SELECT #sql=#sql + ' AND MONTH(CRMDR.Date_Created) in (1,2,3) '
SELECT #sql=#sql + ' ORDER BY CRMDR.Id DESC '
EXEC sp_executesql #sql, N'#Month int, #Year int, #Quater int',
#Month, #Year, #Quater
RETURN
But for #week it gives error.
Running [dbo].[SPReportTimeSpan] ( #Week = 3, #Month = <NULL>, #Year = <NULL>, #Quater = <NULL> ).
Must declare the scalar variable "#startdate".
Column1 Column2
------------------------------ ------------------------------
2013-02-10 00:00:00.0000000 2013-02-17 00:00:00.0000000
No rows affected.
(1 row(s) returned)
#RETURN_VALUE = 0
Finished running [dbo].[SPReportTimeSpan].
I am not getting why its not working with week criteria. Please help if anyone have idea.
#startdate and #enddate are only accessible within the scope of your IF statement:
If (#Week) IS NOT NULL
BEGIN
DECLARE #startdate Date, #enddate Date
EXEC dbo.SPReturnStartEndDateOfSpecifiedWeek #Week, #startdate OUTPUT, #enddate OUTPUT
SELECT #startdate, #enddate
END
Move the declaration outside of the IF statement if you wish to reference these variables elsewhere:
DECLARE #startdate Date, #enddate Date
If (#Week) IS NOT NULL
BEGIN
EXEC dbo.SPReturnStartEndDateOfSpecifiedWeek #Week, #startdate OUTPUT, #enddate OUTPUT
SELECT #startdate, #enddate
END
FYI: The area where you make reference to these variables outside of the IF statement is here:
If (#Week) IS NOT NULL
SELECT #sql=#sql + ' AND (CRMDR.Date_Created) BETWEEN (#startdate) AND (#enddate) '
I got solution of my problem. To solve the problem, I need to explicitly cast datetime values to a character type so the query string can be concatenated as expected.
If (#Week) IS NOT NULL
SELECT #sql=#sql + ' AND (CRMDR.Date_Created) BETWEEN ''' + convert(VARCHAR,#startdate) + ''' AND ''' +convert(VARCHAR,#enddate) + ''''
or this (More Optimized)
SELECT #sql=#sql + ' AND (CRMDR.Date_Created BETWEEN #startdate AND #enddate)'
which needs to add something to sp_executesql
EXEC sp_executesql #sql, N'#Month int, #Year int, #Quater int, #Week int, #startdate datetime, #enddate datetime ',
#Month, #Year, #Quater, #Week, #startdate, #enddate
Your variables are out of scope.
I want to select from table where date with between
but problem is that in database there is not datetime column there is separated dateTime year, month and day
does it possible to create new variable inside stored procedure something like that?
checkin = new DateTime(year, month, day)
this year month and day are columns in datatable
You can convert string to DateTime using the function below:
convert(datetime, '02/15/2012', 101) -- mm/dd/yyyy
You could try something like:
-- dateadd formula borrowed from
-- http://weblogs.sqlteam.com/jeffs/archive/2007/01/02/56079.aspx
with includeDate as (
select column1,
column2,
column3,
dateadd(month,(([year]-1900)*12)+[month]-1,[day]-1) as date
from yourTable
)
select *
from includeDate
where date between #startDate and #endDate
Of course in your stored procedure, you would populate the query with the values from your table, the code below is an example of converting the separate date fields into one datetime value.
I don't know the data type of your day, month and year fields but the following should work if you have an int value:
declare #day int
declare #month int
declare #year int
declare #fulldate smalldatetime
set #day = '1'
set #month = '9'
set #year = '2012'
SELECT #fulldate = Convert(smalldatetime, Cast(#month as varchar(2)) + '/'
+ Cast(#day as varchar(2)) + '/' + Cast(#year as varchar(4)), 101)
select Convert(varchar(10), #fulldate, 101)
If the values are stored as a string:
declare #day varchar(2)
declare #month varchar(2)
declare #year varchar(4)
declare #fulldate smalldatetime
set #day = '1'
set #month = '9'
set #year = '2012'
SELECT #fulldate = Convert(smalldatetime, #month + '/'
+ #day + '/' + #year, 101)
select Convert(varchar(10), #fulldate, 101)
Using SQL Server 2005
Date Time
20060701 090000
20060702 020000
20060703 180000
...
Date and Time datatype is varchar
Tried Query
select Convert(datetime, Convert(char(10), date, 103) + ' ' + Convert(char(8), time, 108), 103) from table
SELECT
CAST(
DATEADD(dd, 0, DATEDIFF(dd, 0, date)) + ' ' +
DATEADD(Day, -DATEDIFF(Day, 0, time), time)
as datetime) from table
It showing error as out of range value.
How to solve this issue.
Need Sql Query Help
First off, why are you storing a DATETIME in a VARCHAR?
This should be able to help
DECLARE #Table TABLE(
Val VARCHAR(20)
)
INSERT INTO #Table (Val) SELECT '20060701 090102'
INSERT INTO #Table (Val) SELECT '20060702 020000'
INSERT INTO #Table (Val) SELECT '20060703 180000'
SELECT *,
CAST(SUBSTRING(Val,1,8) + ' ' + SUBSTRING(Val,10,2) + ':' + SUBSTRING(Val,12,2) + ':' + SUBSTRING(Val,14,2) AS DATETIME)
FROM #Table
I came across a similar issue a few years ago, when importing HL7 messages. Here is a copy of the function I used. It creates a DateTime string with the time component correctly separated into hh:mm:ss, which is needed for the cast to DateTime.
CREATE FUNCTION fn_StringDateTietoDateTime
(
#Date varchar(15)
)
RETURNS datetime
AS
BEGIN
DECLARE #Result DATETIME
SET #Result = NULL
If len(#Date) > 0
BEGIN
SELECT #Result = CAST(SUBSTRING(#hl7date, 1, 8) + ' ' + SUBSTRING(#hl7date, 10, 2) + ':' +
SUBSTRING(#date, 12, 2) + ':' + SUBSTRING(#date,14, 2) AS DATETIME)
END
RETURN #RESULT
END