SQL Server 2008 - MERGE INTO as a loop: syntax error - sql

I am attempting to run an SQL query, which includes a MERGE INTO statement, that loops through each month.
I am getting a couple of syntax errors:
Msg 156, Level 15, State 1, Line 3 Incorrect syntax near the keyword 'INTO'.
Msg 156, Level 15, State 1, Line 10 Incorrect syntax near the keyword 'AS'.
Msg 102, Level 15, State 1, Line 35 Incorrect syntax near ','.
It is printing the month/year correctly so I don't think the problem is in the loop, but the merge statement. I looked around but it looks right to me but I am sure I am missing something. I could have sworn I used this code before and it worked.
Here is the code:
Declare #StartDate As Datetime set #StartDate = '5/1/2015'; --Update to first month that needs to be added
Declare #StopDate As Datetime set #StopDate = '12/1/2015'; --Update to last month that needs to be added
Print 'Start Date ' + Cast(#StartDate as varchar(30));
Print 'Stop Date ' + Cast(#StopDate as varchar(30));
Print 'Total Months ' + Cast(Datediff(Month, #StartDate, #StopDate) + 1 as varchar(30));
Print ' ';
Declare #Date As Datetime set #Date = #StartDate;
Declare #SQL_Cmd As Varchar(Max);
Declare #SQL_Contract_Status As Varchar(Max) set #SQL_Contract_Status =
'
MERGE
INTO ANNUSER1.RPS_Contract_Person_PT AS TGT
USING ( Select
P.Datamart_Timestamp
,P.Contract_ID
,P.DOB
,Ltrim(Rtrim(
CASE
WHEN P.Datamart_Timestamp
< CONVERT(DATETIME, ''2007-06-01 00:00:00'', 102)
AND Len(P.Name_Last) > 25
THEN Substring(P.Name_Last,26,Len(P.Name_Last)-25)
ELSE P.Name_First
END)) As Name_First
,Ltrim(Rtrim(
CASE
WHEN P.Datamart_Timestamp
< CONVERT(DATETIME, ''2007-06-01 00:00:00'', 102)
AND Len(P.Name_Last) > 25
THEN LTrim(Left(P.Name_Last,25))
ELSE P.Name_Last
END)) As Name_Last
,P.Sex
,P.TIN
,P.TIN_Type
,D.Group_Plan_ID
From AT_RPS_2015_05_Contract_Person AS P
INNER JOIN AT_RPS_2015_05_Contract_Data AS D
ON P.Contract_ID = D.Contract_ID
WHERE (P.[Role] IN (''PT''))
) AS SRC
ON ( TGT.Contract_ID = SRC.Contract_ID )
AND ( TGT.DOB = Cast(SRC.DOB as Date)
OR ( TGT.DOB IS NULL
AND SRC.DOB IS NULL ) )
AND ( TGT.Name_First = SRC.Name_First
OR ( TGT.Name_First IS NULL
AND SRC.Name_First IS NULL ) )
AND ( TGT.Name_Last = SRC.Name_Last
OR ( TGT.Name_Last IS NULL
AND SRC.Name_Last IS NULL ) )
AND ( TGT.Sex = SRC.Sex
OR ( TGT.Sex IS NULL
AND SRC.Sex IS NULL ) )
AND ( TGT.TIN = SRC.TIN
OR ( TGT.TIN IS NULL
AND SRC.TIN IS NULL ) )
AND ( TGT.TIN_Type = SRC.TIN_Type
OR ( TGT.TIN_Type IS NULL
AND SRC.TIN_Type IS NULL ) )
WHEN NOT MATCHED
THEN
INSERT
(
Contract_ID
,Sequence_Number
,DOB
,Name_First
,Name_Last
,Sex
,TIN
,TIN_Type
,Datamart_Timestamp
,Group_Plan_ID
)
VALUES
(
SRC.Contract_ID
,Coalesce(
(SELECT Max(Sequence_Number)
FROM ANNUSER1.RPS_Contract_Person_PT AS TGT
WHERE TGT.Contract_ID = SRC.Contract_ID)
,0) + 1
,Cast(SRC.DOB as Datetime)
,SRC.Name_First
,SRC.Name_Last
,SRC.Sex
,SRC.TIN
,SRC.TIN_Type
,Cast(SRC.Datamart_Timestamp As Datetime)
,SRC.Group_Plan_ID
); ';
While #Date <= #StopDate
Begin
Set #SQL_Cmd = Replace(Replace(#SQL_Contract_Status, 'YYYY', Year(#Date)), 'MM', Right('0' + Cast(Month(#Date) As Varchar(2)), 2));
Exec (#SQL_Cmd);
Print Cast(Year(#Date) as varchar(30)) + '_' + Right('0' + Cast(Month(#Date) as varchar(30)),2) + ' ' + Cast(##RowCount as varchar(30));
Set #Date = Dateadd(Month, 1, #date);
End;
GO

Related

How to parse SQL Server String in hour, min and second

I have time stored as PT1H22M59.551S.
There it reads read 1 hour 22 min and 59.551 sec.
What is the most efficient way to split this?
Data could be like this. So no separator is mandatory
PT0S
PT6H4M29.212S
PT0S
PT2M55.126S
PT54M4.12S
PT3H6M5.74S
PT16H27M52.069S
You can also create a function to perform the conversion with basic text manipulation:
CREATE FUNCTION dbo.f_GetTime(#TimeInput VARCHAR(50)) RETURNS TIME
AS BEGIN
SET #TimeInput = REPLACE(REPLACE(#TimeInput, 'PT', ''), 'S', '')
IF CHARINDEX('H', #TimeInput) = 0 -- Add missing H
SET #TimeInput = '0H' + #TimeInput
IF CHARINDEX('M', #TimeInput) = 0 -- Add missing M
SET #TimeInput = REPLACE(#TimeInput, 'H', 'H0M')
RETURN CONVERT(TIME, REPLACE(REPLACE(#TimeInput, 'H', ':'), 'M', ':'))
END
GO
Then you can use it with just scalar queries:
SELECT dbo.f_GetTime('PT1H22M59.551S') AS TimeValue
Or you can use it with tables:
DECLARE #Input TABLE (TimeInput VARCHAR(20))
INSERT #Input VALUES ('PT1H22M59.551S'), ('PT0S'), ('PT6H4M29.212S'), ('PT0S'),
('PT2M55.126S'), ('PT54M4.12S'), ('PT3H6M5.74S'), ('PT16H27M52.069S')
SELECT TimeInput, dbo.f_GetTime(TimeInput) AS TimeValue FROM #Input
This would return:
TimeInput TimeValue
-------------------- ----------------
PT1H22M59.551S 01:22:59.5510000
PT0S 00:00:00.0000000
PT6H4M29.212S 06:04:29.2120000
PT0S 00:00:00.0000000
PT2M55.126S 00:02:55.1260000
PT54M4.12S 00:54:04.1200000
PT3H6M5.74S 03:06:05.7400000
PT16H27M52.069S 16:27:52.0690000
--sql server
declare #data table(
lineid int identity,
a varchar(100),
b varchar(100),
hr varchar(20),
[minute] varchar(20),
[second] varchar(20)
)
insert #data(a) select 'PT0S'
insert #data(a) select 'PT6H4M29.212S'
insert #data(a) select 'PT0S'
insert #data(a) select 'PT2M55.126S'
insert #data(a) select 'PT54M4.12S'
insert #data(a) select 'PT3H6M5.74S'
insert #data(a) select 'PT16H27M52.069S'
update #data
set b = replace(a,'PT','')
update #data
set hr = LEFT(b,charindex('H',b))
update #data
set b = REPLACE(b,hr,'')
update #data
set [minute] = LEFT(b,charindex('M',b))
update #data
set b = REPLACE(b,[minute],'')
update #data
set [second] = LEFT(b,charindex('S',b))
update #data
set b = REPLACE(b,[second],'')
update #data
set [hr] = REPLACE([hr],'H',''),[minute]=REPLACE([minute],'M',''),[second]=REPLACE([second],'S','')
update #data
set hr = isnull(nullif(hr,''),'0'),[minute] = isnull(nullif([minute],''),'0'),[second] = isnull(nullif([second],''),'0')
select *,
[hr] + ' hour'+ case when hr <> '1' then 's ' else ' ' end +
[minute] + ' minute'+ case when [minute] <> '1' then 's ' else ' ' end +
[second] + ' second(s)'
from #data
--sql server
declare #data table(
lineid int identity,
[inboundTime] varchar(100)
)
insert #data([inboundTime]) select 'PT0S'
insert #data([inboundTime]) select 'PT6H4M29.212S'
insert #data([inboundTime]) select 'PT0S'
insert #data([inboundTime]) select 'PT2M55.126S'
insert #data([inboundTime]) select 'PT54M4.12S'
insert #data([inboundTime]) select 'PT3H6M5.74S'
insert #data([inboundTime]) select 'PT16H27M52.069S'
insert #data([inboundTime]) select 'PT52.069S'
update #data
set [inboundTime] = replace([inboundTime],'PT','')
SELECT
INBOUND_H
, INBOUND_M
, INBOUND_S
, INBOUND_H*3600 + INBOUND_M*60 inboundTimeMin
, [inboundTime]
from (
SELECT
IIF ( CHARINDEX('H', [inboundTime]) > 0 , SUBSTRING([inboundTime], 0, CHARINDEX('H', [inboundTime])),0) INBOUND_H
, IIF ( CHARINDEX('M', [inboundTime]) > 0 , SUBSTRING([inboundTime], CHARINDEX('H', [inboundTime])+1,CHARINDEX('M', [inboundTime]) - CHARINDEX('H', [inboundTime])-1 ), 0) INBOUND_M
, SUBSTRING([inboundTime], CHARINDEX('M', [inboundTime])+1,CHARINDEX('S', [inboundTime]) - CHARINDEX('M', [inboundTime])-1 ) INBOUND_S
, [inboundTime]
FROM #data)x
This is a more robust function built off solution:
CREATE FUNCTION dbo.f_GetTime(#TimeInput VARCHAR(50)) RETURNS VARCHAR(50)
AS BEGIN
SET #TimeInput = REPLACE(REPLACE(#TimeInput, 'PT', ''), 'S', '')
IF CHARINDEX('H', REVERSE(#TimeInput)) = 1
SET #TimeInput = #TimeInput + '00:00' -- Add missing S
IF CHARINDEX('M', REVERSE(#TimeInput)) = 1
SET #TimeInput = #TimeInput + '00' -- Add missing S
IF CHARINDEX('H', #TimeInput) = 0 -- Add missing H
SET #TimeInput = '00H' + #TimeInput
IF CHARINDEX('M', #TimeInput) = 0 -- Add missing M
SET #TimeInput = REPLACE(#TimeInput, 'H', 'H0M')
RETURN CONVERT(VARCHAR(50), REPLACE(REPLACE(#TimeInput, 'H', ':'), 'M', ':'))
END
GO

Issue with full outer join in SQL Server

When I use below 2 queries separately I get output successfully
Query #1
DECLARE #ID VARCHAR(1000)
SET #ID = ''
SELECT #ID = #ID + CAST(int_ID AS VARCHAR(1000))
FROM MATRIX_RELATIONSHIP
SELECT COUNT(int_ID) [Count], YEAR(dt_5841_OF) [date]
FROM TRANS_IDENTIFICATIONS
WHERE smallint_209_ME = 4
AND CHARINDEX(CONVERT(VARCHAR, int_ID), ('''' + Replace((#ID),',',''',''') + '''')) > 0
GROUP BY YEAR(dt_5841_OF);
Output:
Count | year
02 2016
Query #2
SELECT
COUNT(*) [Count1], YEAR(dt_modifiedOn) [date]
FROM
MATRIX_RELATIONSHIP
GROUP BY
YEAR(dt_modifiedOn);
Output:
Count | year
02 2016
But when I use both queries to form a full outer join something like below:
SELECT
tab1.Count, tab2.Count1, tab1.date
FROM
(DECLARE #ID VARCHAR(1000)
SET #ID = ''
SELECT #ID = #ID+CAST(int_ID AS VARCHAR(1000))
FROM MATRIX_RELATIONSHIP
SELECT COUNT(int_ID) [Count], YEAR(dt_5841_OF) [date]
FROM TRANS_IDENTIFICATIONS
WHERE smallint_209_ME = 4
AND CHARINDEX(convert(varchar,int_ID), ('''' + Replace((#ID),',',''',''') + '''')) > 0
GROUP BY YEAR(dt_5841_OF)) tab1
FULL OUTER JOIN
(SELECT COUNT(*) [Count1], YEAR(dt_modifiedOn) [date]
FROM MATRIX_RELATIONSHIP
GROUP BY YEAR(dt_modifiedOn)) tab2 ON tab1.date = tab2.date;
I get these errors:
Msg 156, Level 15, State 1, Line 2
Incorrect syntax near the keyword 'DECLARE'.
Msg 102, Level 15, State 1, Line 4
Incorrect syntax near ')'.
Msg 102, Level 15, State 1, Line 7
Incorrect syntax near 'tab2'.
Expected result
Count | Count1 | year
02 02 2016
EDIT
I have tried placing declare and set outside the query too but still there the issue persists
DECLARE #ID VARCHAR(1000) SET #ID=''
SELECT tab1.Count,tab2.Count1,tab1.date from
( SELECT #ID= #ID+CAST(int_ID AS VARCHAR(1000))
from MATRIX_RELATIONSHIP SELECT COUNT(int_ID)[Count],YEAR(dt_5841_OF)[date] FROM TRANS_IDENTIFICATIONS WHERE smallint_209_ME=4 and CHARINDEX(convert(varchar,int_ID), ('''' + Replace((#ID),',',''',''') + '''')) >
0 GROUP BY YEAR(dt_5841_OF)) tab1
FULL OUTER JOIN
(SELECT COUNT(*)[Count1],YEAR(dt_modifiedOn)[date]
FROM MATRIX_RELATIONSHIP GROUP BY YEAR(dt_modifiedOn)) tab2
ON tab1.date=tab2.date;
Which leads to another set of errors:
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near '='.
Msg 102, Level 15, State 1, Line 5
Incorrect syntax near ')'.
Msg 102, Level 15, State 1, Line 8
Incorrect syntax near 'tab2'.
DECLARE #ID VARCHAR(1000)
SET #ID='';
SELECT #ID = #ID + CAST(int_ID AS VARCHAR(1000)) from MATRIX_RELATIONSHIP;
SELECT MAX(Count) AS Count, MAX(Count1) AS Count1, date
FROM
(
SELECT COUNT(int_ID)[Count], null AS [Count1], YEAR(dt_5841_OF)[date]
FROM TRANS_IDENTIFICATIONS
WHERE smallint_209_ME = 4
and CHARINDEX(convert(varchar,int_ID), ('''' + Replace((#ID),',',''',''') + '''')) >
0 GROUP BY YEAR(dt_5841_OF)
UNION ALL
SELECT NULL AS [Count], COUNT(*)[Count1],YEAR(dt_modifiedOn)[date]
FROM MATRIX_RELATIONSHIP
GROUP BY YEAR(dt_modifiedOn)
)AS temp
GROUP BY [date]
this is not a valid from
it is two select statements
from
( DECLARE #ID VARCHAR(1000)
SET #ID='' SELECT #ID= #ID+CAST(int_ID AS VARCHAR(1000))
from MATRIX_RELATIONSHIP
SELECT COUNT(int_ID)[Count],YEAR(dt_5841_OF)[date]
FROM TRANS_IDENTIFICATIONS
WHERE smallint_209_ME=4
and CHARINDEX(convert(varchar,int_ID), ('''' + Replace((#ID),',',''',''') + '''')) > 0
GROUP BY YEAR(dt_5841_OF)
)
Your DECLARE and SET has to be outside of the SELECT. But what is its purpose?
remove the DECLARE #ID VARCHAR(1000);
SET #ID='' from the select statement.
Also declare the variable at the top of your statement
and rather writing two separate select statement use inner join on int_id and then do the outer join it will work
DECLARE #ID VARCHAR(1000)
SET #ID = ''
select * from
(
SELECT #ID+ CAST(MATRIX_RELATIONSHIP.int_ID AS varchar(1000)) AS count1, COUNT(TRANS_IDENTIFICATIONS.int_ID) AS count2, YEAR(TRANS_IDENTIFICATIONS.dt_5841_OF) AS date1
FROM MATRIX_RELATIONSHIP INNER JOIN
TRANS_IDENTIFICATIONS ON MATRIX_RELATIONSHIP.int_ID = TRANS_IDENTIFICATIONS.int_ID
WHERE (TRANS_IDENTIFICATIONS.smallint_209_ME = 4) AND (CHARINDEX(CONVERT(varchar, TRANS_IDENTIFICATIONS.int_ID), '''' + REPLACE(#ID, ',', ''',''') + '''') > 0)
GROUP BY YEAR(TRANS_IDENTIFICATIONS.dt_5841_OF),MATRIX_RELATIONSHIP.int_ID
union
(
SELECT '' as count1, COUNT(*) [Count2], YEAR(dt_modifiedOn) [date1]
FROM MATRIX_RELATIONSHIP
GROUP BY YEAR(dt_modifiedOn)
)
) as tbl
I hope this works for you... Do let me know

SQL Server : comma-separated List based on offset values

The SQL query looks like this:
Declare #Values nvarchar(max) , #From int , #To int
Set #Values = 'a,b,c,d,e,f,g,h,i,j'
Set #From = 3 , #To = 7
The values must be split into rows based on #From and #To. Based on the above query, required output is
c d e f g
Any help would be appreciated.
Disclaimer: I'm the owner of the project Eval SQL.NET
If you have a C# background, you may might consider this library which let you use C# syntax directly in T-SQL
DECLARE #Values NVARCHAR(MAX) ,
#From INT ,
#To INT
SELECT #Values = 'a,b,c,d,e,f,g,h,i,j' ,
#From = 3 ,
#To = 7
-- The index start at 0 and not at 1 in C#
DECLARE #sqlnet SQLNET = SQLNET::New('
values.Split('','').Skip(from - 1).Take(to - from + 1)')
.ValueString('values', #Values)
.Val('from', #From)
.Val('to', #to)
-- In multiple rows
SELECT *
FROM [dbo].[SQLNET_EvalTVF_1](#sqlnet)
-- In same rows
SELECT SQLNET::New('
var splits = values.Split('','').Skip(from - 1).Take(to - from + 1).ToList();
return string.Join('' '', splits);')
.ValueString('values', #Values)
.Val('from', #From)
.Val('to', #to)
.Eval()
You need a string splitter for this. Here is DelimitedSplit8k by Jeff Moden.
DECLARE #Values NVARCHAR(MAX),
#From INT,
#To INT
SELECT #Values = 'a,b,c,d,e,f,g,h,i,j',
#From = 3,
#To = 7
SELECT STUFF((
SELECT ' ' + Item
FROM dbo.DelimitedSplit8K(#Values, ',')
WHERE ItemNumber BETWEEN #From AND #To
FOR XML PATH('')
), 1, 1, '')
You can use this query:
declare #Values nvarchar(max)
, #From int
, #To int
set #Values = 'a,b,c,d,e,f,g,h,i,j'
set #From = 3
set #To = 7
;with cte as(
select substring(#Values, charindex(',', #Values, 1) + 1, 4000) as st
, substring(#Values, 1, charindex(',', #Values, 1) - 1) ch
, 1 as rn
union all
select substring(st, t + 1, 4000) as st
, substring(st, 1, t - 1) ch
, rn + 1 as rn
from cte
cross apply (select case when charindex(',', st, 1) = 0 then 8000 else charindex(',', st, 1) end) t(t)
where rn < #To
and datalength(st) > 0)
select stuff((
select ' ' + ch as 'text()'
from cte
where rn between #From and #To
order by rn
for xml path('')), 1, 1, '')
option (maxrecursion 0)

SQL OpenQuery - Escaping Quotes

Been trying for some hours to convert this to a query I can use with OPENQUERY in SQL Server 2014 (to use with Progress OpenEdge 10.2B via ODBC). Can't seem to get the escaping of the quote right. Can anyone offer some assistance? Is there a tool to do it?
(There's a SQL table called #tAPBatches that is used in this, but I omitted it from this code)
DECLARE
#NoDays AS INT = 30
,#Prefix AS VARCHAR(5) = 'M_AP_'
SELECT
#Prefix + LTRIM(CAST(gh.[Batch-Number] AS VARCHAR(20))) AS BatchNo
,gh.[Batch-Number] AS BatchNo8
, aph.[Reference-number] AS InvoiceNo
,aph.[Voucher-Number] AS VoucherNo
,aph.[Amount] AS InvoiceTotal
,gh.[Journal-Number] AS JournalNo
,4 AS FacilityID
,CASE aph.[voucher-type]
WHEN 'DM' THEN 5
ELSE 1
END AS DocType
,apb.[Batch-Desc] AS BatchDesc
,apb.[Posting-Date] AS PostingDate
,apb.[Posting-Period]
,apb.[Posting-Fiscal-Year]
,apb.[Batch-Status]
,apb.[Expected-Count]
,apb.[Expected-Amount]
,apb.[Posted-To-GL-By]
,'Broadview' AS FacilityName
,apb.[Date-Closed] AS BatchDate
,gh.[Posted-by] AS PostUser
,gh.[Posted-Date] AS PostDT
,gh.[Created-Date] AS CreateDT
,gh.[Created-By] AS CreateUser
,aph.[Supplier-Key] AS VendorID
,sn.[Supplier-Name]
,aph.[Invoice-Date] AS InvoiceDate
,-1 AS Total
,-1 AS Discount
,gh.[Posted-by] AS Username
,CASE gt.[Credit-Debit]
WHEN 'CR' THEN LEFT(CAST(gacr.[GL-Acct] AS VARCHAR(20)), 2) + '.' + SUBSTRING(CAST(gacr.[GL-Acct] AS VARCHAR(20)), 3, 6) + '.'
+ RIGHT(CAST(gacr.[GL-Acct] AS VARCHAR(20)), 3)
ELSE NULL
END AS GLCreditAcct
,CASE gt.[Credit-Debit]
WHEN 'DR' THEN LEFT(CAST(gacr.[GL-Acct] AS VARCHAR(20)), 2) + '.' + SUBSTRING(CAST(gacr.[GL-Acct] AS VARCHAR(20)), 3, 6) + '.'
+ RIGHT(CAST(gacr.[GL-Acct] AS VARCHAR(20)), 3)
ELSE NULL
END AS GLDebitAcct
,CASE gt.[Credit-Debit]
WHEN 'CR' THEN gacr.[Report-Label]
ELSE NULL
END AS GLCreditDesc
,CASE gt.[Credit-Debit]
WHEN 'DR' THEN gacr.[Report-Label]
ELSE NULL
END AS GLDebitDesc
,'D' AS [Status]
,aph.[PO-Number] AS PoNo
,aph.[Terms-Code] AS TermsCode
,aph.[Due-Date] AS DueDate
,'' AS Comments
,aph.[Discount-Date] AS DiscountDate
,aph.[Discount-Amount] AS DiscountAmount
,aph.[Discount-Taken] AS DiscountTaken
,aph.[Amount] AS APAmount
,gt.[Amount]
,'BA REGULAR ' AS CheckBookID --ToDO
,0 AS Transferred
,aph.[voucher-type] AS VoucherType
,gt.[Credit-Debit]
,gacr.[Account-type]
,aph.[Freight-Ref-Num]
FROM
[Progress].[GAMS1].pub.[GL-Entry-Header] gh
INNER JOIN [Progress].[GAMS1].pub.[gl-entry-trailer] gt ON gt.[System-ID] = gh.[System-ID] AND gt.[Origin] = gh.[Origin] AND gt.[Journal-Number] = gh.[Journal-Number]
INNER JOIN [Progress].[GAMS1].pub.[apinvhdr] aph ON (gh.[Journal-Number] = aph.[Journal-Number]
OR (gh.[Journal-Num-Reversal-Of] = aph.[Journal-Number] AND aph.[Journal-Number] <> ' ' AND gh.[Journal-Num-Reversal-Of] <> ' '))
AND gh.[system-id] = aph.[system-id-gl]
AND gh.origin = 'inv'
AND gh.[system-id] = 'arcade'
INNER JOIN [Progress].[GAMS1].pub.[APInvoiceBatch] apb ON gh.[Batch-number] = apb.[Batch-number]
AND apb.[system-id] = 'lehigh'
AND apb.[Posted-To-GL] = 1
INNER JOIN [Progress].[GAMS1].pub.[GL-accts] gacr ON gacr.[system-id] = gt.[system-id]
AND gacr.[Gl-Acct-Ptr] = gt.[GL-Acct-Ptr]
INNER JOIN [Progress].[GAMS1].pub.[suppname] sn ON sn.[Supplier-Key] = aph.[Supplier-Key]
AND sn.[system-id] = 'arcade'
WHERE
gh.[Posted-Date] > CAST(DATEADD(DAY, -#NoDays, GETDATE()) AS DATE)
AND case
when CAST(gh."Posting-Period" as int) < 10 then gh."Posting-Year" + '0' + ltrim(gh."Posting-Period")
else gh."Posting-Year" + Ltrim(gh."Posting-Period")
end > '201501'
AND gh.[Batch-number] NOT IN (SELECT
BatchNo COLLATE SQL_Latin1_General_CP1_CI_AS
FROM
#tAPBatches)
TIA
MArk
Here's an example of what's giving me a syntax error. This works, but "M_AP_" is a parameter passed to SP
DECLARE
#NoDays AS INT = 5
,#Prefix AS VARCHAR(5) = 'M_AP_';
DECLARE
#InterestDate AS varchar(20)
SELECT #InterestDate = CAST(CAST(DATEADD(DAY, -#NoDays, GETDATE()) AS DATE) AS VARCHAR(20))
SELECT * FROM OPENQUERY(PROGRESS,
'SELECT TOP 100 ''M_AP_'' + LTRIM(CAST(gh."Batch-Number" AS VARCHAR(20))) AS BatchNo
, gh."Batch-Number"
This works, but when I try to swap in the variable I get Incorrect Syntax near '+'
DECLARE
#NoDays AS INT = 5
,#Prefix AS VARCHAR(5) = 'M_AP_';
DECLARE
#InterestDate AS varchar(20)
SELECT #InterestDate = CAST(CAST(DATEADD(DAY, -#NoDays, GETDATE()) AS DATE) AS VARCHAR(20))
SELECT * FROM OPENQUERY(PROGRESS,
'SELECT TOP 100 '' ' + #Prefix + ' '' + LTRIM(CAST(gh."Batch-Number" AS VARCHAR(20))) AS BatchNo
, gh."Batch-Number"
FROM
"GAMS1".pub."GL-Entry-Header" gh
OPENQUERY will only support a string literal query that is less than 8K. You might be running into that limit if you've got even more code that you're not showing here. Make sure that your query is less than 8000 bytes, or create procedures or views to reduce the size of your query.
It only accepts a single string literal... so if you are trying to concatenate strings and parameters together, it will not work. There are some ways to work around this by using dynamic SQL or creating supporting tables or views for filters.

sql query including month columns?

I was wondering if I could get some ideas or direction on a sql query that would output column months. Here is my current query..
select A.assetid, A.Acquisition_Cost, B.modepreciaterate from FA00100 A
inner join FA00200 B on A.assetindex = B.assetindex
where MoDepreciateRate != '0'
I would like to add more columns that look as such:
select assetid, acquisition_cost, perdeprrate, Dec_2012, Jan_2013, Feb_2013....
where Dec_2012 = (acquisition_cost - MoDepreciateRate*(# of months))
and Jan_2013 = (acquisition_cost - MoDepreciateRate*(# of months))
where # of months can be changed.
Any help would be really appreciated. Thank you!
Here is an example of what I would like the output to be with '# of months' = 4
assetid SHRTNAME Acquisition_Cost perdeprrate Dec_2012 Jan_2013 Feb_2013 Mar_2013
CS-013 GEH INTEG 17490.14 485.83 17004.31 16518.48 16032.65 15546.82
CS-014 WEB BRD 14560 404.4507 14155.5493 13751.0986 13346.6479 12942.1972
Try This:
--setup
create table #fa00100 (assetId int, assetindex int, acquisitionCost int, dateAcquired date)
create table #fa00200 (assetIndex int, moDepreciateRate int, fullyDeprFlag nchar(1), fullyDeprFlagBit bit)
insert #fa00100
select 1, 1, 100, '2012-01-09'
union select 2, 2, 500, '2012-05-09'
insert #fa00200
select 1, 10, 'N', 0
union select 2, 15, 'Y', 1
.
--solution
create table #dates (d date not null primary key clustered)
declare #sql nvarchar(max)
, #pivotCols nvarchar(max)
, #thisMonth date
, #noMonths int = 4
set #thisMonth = cast(1 + GETUTCDATE() - DAY(getutcdate()) as date)
select #thisMonth
while #noMonths > 0
begin
insert #dates select DATEADD(month,#noMonths,#thisMonth)
set #noMonths = #noMonths - 1
end
select #sql = ISNULL(#sql + NCHAR(10) + ',', '')
--+ ' A.acquisitionCost - (B.moDepreciateRate * DATEDIFF(month,dateAcquired,''' + convert(nvarchar(8), d, 112) + ''')) ' --Original Line
+ ' case when A.acquisitionCost - (B.moDepreciateRate * DATEDIFF(month,dateAcquired,''' + convert(nvarchar(8), d, 112) + ''')) <= 0 then 0 else A.acquisitionCost - (B.moDepreciateRate * DATEDIFF(month,dateAcquired,''' + convert(nvarchar(8), d, 112) + ''')) end ' --new version
+ quotename(DATENAME(month, d) + '_' + right(cast(10000 + YEAR(d) as nvarchar(5)),4))
from #dates
set #sql = 'select A.assetid
, A.acquisitionCost
, B.moDepreciateRate
,' + #sql + '
from #fa00100 A
inner join #fa00200 B
on A.assetindex = B.assetindex
where B.fullyDeprFlag = ''N''
and B.fullyDeprFlagBit = 0
'
--nb: B.fullyDeprFlag = ''N'' has double quotes to avoid the quotes from terminating the string
--I've also included fullyDeprFlagBit to show how the SQL would look if you had a bit column - that will perform much better and will save space over using a character column
print #sql
exec(#sql)
drop table #dates
.
--remove temp tables from setup
drop table #fa00100
drop table #fa00200