Move aggregate logic to separate function in SQL Server 2008 R2 - sql

Please correct me if I'm using the wrong terminology or description, but I have business logic within an aggregate function (MIN and MAX). I wish to move to the logic to it's own function. I wish to do this so I don't have to make multiple changes in different locations when the client requests. I have the following
SELECT DISTINCT
DATA_MONTH,
DATA_DATE,
CASE
WHEN MIN(DATA_YEAR) = MAX(DATA_YEAR)
AND MIN(DATA_YEAR) = #BEGIN_YR THEN 'Started'
WHEN MIN(DATA_YEAR) = MAX(DATA_YEAR)
AND MIN(DATA_YEAR) <> #CURRENTFY THEN
CAST((MIN(DATA_YEAR) %100)-1 AS VARCHAR)
+ '/'
+ CAST(MIN(DATA_YEAR)%100 AS VARCHAR)
WHEN MIN(DATA_YEAR) <> MAX(DATA_YEAR)
AND MIN(DATA_YEAR) = #BEGIN_YR THEN
'Started' + ' from '
+ CAST((MAX(DATA_YEAR) %100)-1 AS VARCHAR)
+ '/'
+ CAST(MAX(DATA_YEAR)%100 AS VARCHAR)
ELSE CAST((MIN(DATA_YEAR) %100)-1 AS VARCHAR)
+ '/'
+ CAST((MIN(DATA_YEAR) %100) AS VARCHAR)
+ ' through '
+ CAST((MAX(DATA_YEAR) %100)-1 AS VARCHAR)
+ '/'
+ CAST(MAX(DATA_YEAR)%100 AS VARCHAR)
END AS [STATUS]
FROM TABLE_A
WHERE DATA_MONTH IN ('03', '04')
AND DATA_DATE = '01'
GROUP BY DATA_MONTH,
DATA_DATE
Which I would like to change it to this:
SELECT DISTINCT
DATA_MONTH,
DATA_DATE,
dbo.getStatus(DATA_YEAR) AS [STATUS]
FROM TABLE_A
WHERE DATA_MONTH IN ('03', '04')
AND DATA_DATE = '01'
GROUP BY DATA_MONTH,
DATA_DATE
The logic for getStatus() has the case statements and can output:
NULL
Started
15/16
Started from 15/16
15/16 through 16/17
My question is how can I restructure my logic to make this possible as I have a GROUP BY clause?

You can create a scalar user defined function and use it in the SELECT. Since it needs to be aggregated, you should be able to throw a MAX around it.
Although, I'd be interested to see if this works.
Nicarus is probably right and that you need a user defined aggregate function.
USE [AdventureWorks2012]
GO
/****** Object: Table [dbo].[TABLE_A] Script Date: 7/20/2016 3:23:39 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[TABLE_A](
[DATA_DATE] [date] NULL,
[DATA_MONTH] [int] NOT NULL,
[DATA_YEAR] [int] NOT NULL
) ON [PRIMARY]
GO
INSERT INTO TABLE_A SELECT CAST ('2016-03-02' as DATE) AS DATA_DATE, 3 as DATA_MONTH, 2016 AS DATA_YEAR
CREATE FUNCTION dbo.getStatus(#MAXYR int, #MINYR int, #BEGIN_YR int ,#CURRENTFY int)
RETURNS varchar(30)
AS
BEGIN
DECLARE #ret varchar(30);
SELECT #ret = CASE
WHEN #MINYR = #MAXYR
AND #MINYR = #BEGIN_YR THEN 'Started'
WHEN #MINYR = #MAXYR
AND #MINYR <> #CURRENTFY THEN
CAST((#MINYR %100)-1 AS VARCHAR)
+ '/'
+ CAST(#MINYR%100 AS VARCHAR)
WHEN #MINYR <> #MAXYR
AND #MINYR = #BEGIN_YR THEN
'Started' + ' from '
+ CAST((#MAXYR %100)-1 AS VARCHAR)
+ '/'
+ CAST(#MAXYR%100 AS VARCHAR)
ELSE CAST((#MINYR %100)-1 AS VARCHAR)
+ '/'
+ CAST((#MINYR %100) AS VARCHAR)
+ ' through '
+ CAST((#MAXYR %100)-1 AS VARCHAR)
+ '/'
+ CAST(#MAXYR%100 AS VARCHAR)
END
RETURN #ret;
END;
DECLARE #BEGIN_YR INT = 2;
DECLARE #CURRENTFY int = 2016;
SELECT DISTINCT
DATA_MONTH,
DATA_DATE,
dbo.getStatus(MAX(DATA_YEAR), MIN(DATA_YEAR), #BEGIN_YR, #CURRENTFY) as STATUS
FROM TABLE_A
GROUP BY DATA_MONTH, DATA_DATE

Related

SQL Server job failing 10-20% of the time for "there is already an object named '##tmp_tbl' in the DB

I have a SQL Server 2008 job set to run every 15 minutes, calling a stored procedure. Normally this runs without issue, but lately it has been failing at random times throughout the day and causing issues with a report that is calling that stored procedure.
The original query has always contained a check to drop the table if exists
IF (SELECT OBJECT_ID('tempdb..##tmp_tbl')) IS NOT NULL
DROP TABLE ##tmp_tbl
I also tried creating a new procedure with the same parameters to test the query and changing it based on other questions I have seen here:
IF SELECT OBJECT_ID('tempdb..##tmp_tbl') IS NOT NULL
BEGIN
DROP TABLE ##tmp_tbl
END
Or by changing all of the check's to:
IF (SELECT OBJECT_ID('tempdb..##tmp_tbl')) IS NOT NULL
DROP TABLE ##tmp_tbl
but all this did was kill the new test job I created, it now runs for an average of 45 minutes and fails almost every time (maybe I did it wrong? I made the change and hit execute, should I have disabled the job first?)
Does anyone know why this would fail 10-20% of the time for a ##tmp_tbl when it runs fine most of the day?
Full code below:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_GetGoaling_Outs]
#site varchar(4)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sqlStr nvarchar(max)
DECLARE #sqlStr2 nvarchar(max)
DECLARE #openQueryStr nvarchar(max)
DECLARE #so nvarchar(15)
DECLARE #goalDate nvarchar(10)
DECLARE #wc nvarchar(35)
DECLARE #wc2 nvarchar(35)
DECLARE #goal_yield smallint
DECLARE #early_goal_date nvarchar(10)
DECLARE #early_goal_yield smallint
--Declare #site varchar(4)
--set #site = 'OR01'
--[sp_GetGoaling_Outs] 'OR01'
--set #so = '147300'
--set #goalDate = '2016/02/24'
IF (SELECT OBJECT_ID('tempdb..##tmp_tbl')) IS NOT NULL
DROP TABLE ##tmp_tbl
IF EXISTS (SELECT TOP 1 * FROM GoalTemp) --If the Goal Temp Table is empty, then do not run
BEGIN
TRUNCATE TABLE Goal
INSERT INTO GOAL (shop_order,work_center, goal_yield, goal_date, early_goal_yield, early_goal_date)
SELECT shop_order,work_center, goal_yield, goal_date, early_goal_yield, early_goal_date
FROM GOALTemp
DECLARE db_cursor CURSOR FOR
SELECT shop_order, work_center, goal_date, goal_yield, early_goal_yield, early_goal_date
FROM Goal
--WHERE goal_date > DATEADD(mm,-2,GETDATE())
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #so, #wc, #goalDate, #goal_yield, #early_goal_yield, #early_goal_date
WHILE ##FETCH_STATUS = 0
BEGIN
SET #wc2 = 'BDL_' + #wc
----------------------------------------GET Yield (Outs) for work center to current date AND to end goal date--------------------------------------
set #sqlStr = 'SELECT site, shop_order, work_center, goal_date, wc_outs,
(SELECT WC_OUTS_TO_NEED_DATE
FROM (
--count the outs for the work center/max reporting operation seq
SELECT DISTINCT
COUNT(*) OVER (PARTITION BY shop_order, work_center ORDER BY shop_order ) WC_OUTS_TO_NEED_DATE
FROM (
SELECT *
FROM (
--get the work center, reporting operation seq, and max reporting op seq for the route
SELECT base.site, base.shop_order,base.sfc, base.router, base.router_revision,
base.completeDateTime ,base.operation, base.work_center, cf.value rep_op_seq
, row_number() over (partition by base.shop_order, base.sfc, base.router, base.router_revision, base.operation, base.work_center order by base.shop_order) rownumber
, MAX(cf.value) OVER (PARTITION BY base.work_center ) AS max_wc_op_rpt_seq
, MAX(cf.value) OVER (PARTITION BY base.work_center )+1 AS max_wc_op_rpt_seqPlus
FROM (
--get only completes during the filtered time for the active shop orders
SELECT DISTINCT al.site, al.router, al.router_revision, al.sfc,
al.activity, al.reporting_center_bo
,substr(al.shop_order_bo,instr( al.shop_order_bo, '','') + 1,length( al.shop_order_bo) - instr( al.shop_order_bo, '','')) shop_order
,(al.date_time + to_number(concat(substr(extract(TIMEZONE_OFFSET from systimestamp), 1, 1), substr(extract(TIMEZONE_OFFSET from systimestamp), 12, 2))) / 24 ) completeDateTime
, substr(o.reporting_center_bo,instr(o.reporting_center_bo, '','') + 1,length(o.reporting_center_bo)) work_center
, o.handle oHandle
, o.operation
FROM
wip.activity_log al,
wip.operation o
WHERE
al.action_code = ''COMPLETE''
AND al.operation = o.operation
AND al.site = ''' + #site + '''
AND trunc(al.date_time + to_number(concat(substr(extract(TIMEZONE_OFFSET from systimestamp), 1, 1), substr(extract(TIMEZONE_OFFSET from systimestamp), 12, 2))) / 24 )
<= TO_DATE(''' + #goalDate + ''',''yyyy/mm/dd'')
AND substr(al.shop_order_bo,instr( al.shop_order_bo, '','') + 1,length( al.shop_order_bo) - instr( al.shop_order_bo, '',''))
= ''' + #so + '''
) base
,wip.router r, wip.router_step rs, wip.router_operation ro
,(SELECT SUBSTR(handle,instr(handle, '','') + 1,length(handle) - instr(handle, '','') - 2) operation, attribute, value
FROM wip.custom_fields
WHERE attribute = ''REPORT_OP_SEQUENCE'' ) cf
WHERE
base.router = r.router (+)
AND base.router_revision = r.revision (+)
AND r.handle = rs.router_bo (+)
AND rs.handle = ro.router_step_bo (+)
AND substr( ro.operation_bo,1,length(ro.operation_bo)-2) = substr( base.oHandle,1,length(base.oHandle)-2)
AND base.operation = cf.operation (+)
AND base.work_center = ''' + #wc2 + '''
)
WHERE rownumber = 1
)
WHERE rep_op_seq = max_wc_op_rpt_seq
) ) WC_OUTS_TO_NEED_DATE '
SET #sqlStr2 = ' FROM (
SELECT DISTINCT site, shop_order
, work_center, ''' + #goalDate + ''' as goal_date,
COUNT(*) OVER (PARTITION BY shop_order, work_center ORDER BY shop_order ) WC_OUTS
FROM (
SELECT *
FROM (
--get the work center, reporting operation seq, and max reporting op seq for the route
SELECT base.site, base.shop_order,base.sfc, base.router, base.router_revision,
base.completeDateTime ,base.operation, base.work_center, cf.value rep_op_seq
, row_number() over (partition by base.shop_order, base.sfc, base.router, base.router_revision, base.operation, base.work_center order by base.shop_order) rownumber
, MAX(cf.value) OVER (PARTITION BY base.work_center ) AS max_wc_op_rpt_seq
, MAX(cf.value) OVER (PARTITION BY base.work_center )+1 AS max_wc_op_rpt_seqPlus
FROM (
--get only completes during the filtered time for the active shop orders
SELECT DISTINCT al.site, al.router, al.router_revision, al.sfc,
al.activity, al.reporting_center_bo
,substr(al.shop_order_bo,instr( al.shop_order_bo, '','') + 1,length( al.shop_order_bo) - instr( al.shop_order_bo, '','')) shop_order
,(al.date_time + to_number(concat(substr(extract(TIMEZONE_OFFSET from systimestamp), 1, 1), substr(extract(TIMEZONE_OFFSET from systimestamp), 12, 2))) / 24 ) completeDateTime
, substr(o.reporting_center_bo,instr(o.reporting_center_bo, '','') + 1,length(o.reporting_center_bo)) work_center
, o.handle oHandle
, o.operation
FROM
wip.activity_log al,
wip.operation o
WHERE
al.action_code = ''COMPLETE''
AND al.operation = o.operation
AND al.site = ''' + #site + '''
-- AND trunc(al.date_time + to_number(concat(substr(extract(TIMEZONE_OFFSET from systimestamp), 1, 1), substr(extract(TIMEZONE_OFFSET from systimestamp), 12, 2))) / 24 )
-- <= TO_DATE(''' + #goalDate + ''',''yyyy/mm/dd'')
AND substr(al.shop_order_bo,instr( al.shop_order_bo, '','') + 1,length( al.shop_order_bo) - instr( al.shop_order_bo, '',''))
= ''' + #so + '''
) base
,wip.router r , wip.router_step rs, wip.router_operation ro
,(SELECT SUBSTR(handle,instr(handle, '','') + 1,length(handle) - instr(handle, '','') - 2) operation, attribute, value
FROM wip.custom_fields
WHERE attribute = ''REPORT_OP_SEQUENCE'' ) cf
WHERE
base.router = r.router (+)
AND base.router_revision = r.revision (+)
AND r.handle = rs.router_bo (+)
AND rs.handle = ro.router_step_bo (+)
AND substr( ro.operation_bo,1,length(ro.operation_bo)-2) = substr( base.oHandle,1,length(base.oHandle)-2)
AND base.operation = cf.operation (+)
AND base.work_center = ''' + #wc2 + '''
)
WHERE rownumber = 1
)
WHERE rep_op_seq = max_wc_op_rpt_seq
)'
SET #openQueryStr = 'select * into ##tmp_tbl FROM OPENQUERY(WIP, ''' + REPLACE(#sqlStr, '''', '''''') + REPLACE(#sqlStr2, '''', '''''') + ''')'
EXEC(#openQueryStr)
--print #sqlStr
--print #sqlStr2
UPDATE goal
SET actual_yield = t.wc_outs,
actual_yield_to_need_date = t.WC_OUTS_TO_NEED_DATE
FROM goal g inner join ##tmp_tbl t ON g.shop_order = t.shop_order
AND g.work_center = Right(t.work_center, LEN(t.work_center)-4)
AND g.goal_date = t.goal_date
---------------------------IF THERE IS AN EARLY GOAL, THEN GET THE OUTS FOR THAT GOAL up to the early goal date--------------
IF (#early_goal_date IS NOT NULL)
BEGIN
IF OBJECT_ID('tempdb..##tmp_tbl') IS NOT NULL
DROP TABLE ##tmp_tbl
set #sqlStr = 'SELECT DISTINCT site, shop_order
, work_center, ''' + #early_goal_date + ''' as goal_date,
COUNT(*) OVER (PARTITION BY shop_order, work_center ORDER BY shop_order ) WC_OUTS
FROM (
SELECT *
FROM (
SELECT base.site, base.shop_order, base.sfc, base.router, base.router_revision,
base.completeDateTime ,base.operation, base.work_center, cf.value rep_op_seq
, row_number() over (partition by base.shop_order, base.sfc, base.router, base.router_revision, base.operation, base.work_center order by base.shop_order) rownumber
, MAX(cf.value) OVER (PARTITION BY base.work_center ) AS max_wc_op_rpt_seq
, MAX(cf.value) OVER (PARTITION BY base.work_center )+1 AS max_wc_op_rpt_seqPlus
FROM (
SELECT DISTINCT al.site, al.router, al.router_revision, al.sfc,
al.activity, al.reporting_center_bo
,substr(al.shop_order_bo,instr( al.shop_order_bo, '','') + 1,length( al.shop_order_bo) - instr( al.shop_order_bo, '','')) shop_order
,(al.date_time + to_number(concat(substr(extract(TIMEZONE_OFFSET from systimestamp), 1, 1), substr(extract(TIMEZONE_OFFSET from systimestamp), 12, 2))) / 24 ) completeDateTime
, substr(o.reporting_center_bo,instr(o.reporting_center_bo, '','') + 1,length(o.reporting_center_bo)) work_center
, o.handle oHandle
, o.operation
FROM
wip.activity_log al,
wip.operation o
WHERE
al.action_code = ''COMPLETE''
AND al.operation = o.operation
AND al.site = ''' + #site + '''
AND trunc(al.date_time + to_number(concat(substr(extract(TIMEZONE_OFFSET from systimestamp), 1, 1), substr(extract(TIMEZONE_OFFSET from systimestamp), 12, 2))) / 24 )
<= TO_DATE(''' + #early_goal_date + ''',''yyyy/mm/dd'')
AND substr(al.shop_order_bo,instr( al.shop_order_bo, '','') + 1,length( al.shop_order_bo) - instr( al.shop_order_bo, '',''))
= ''' + #so + '''
) base
,wip.router r , wip.router_step rs , wip.router_operation ro
,(SELECT SUBSTR(handle,instr(handle, '','') + 1,length(handle) - instr(handle, '','') - 2) operation, attribute, value
FROM wip.custom_fields
WHERE attribute = ''REPORT_OP_SEQUENCE'' ) cf
WHERE
base.router = r.router (+)
AND base.router_revision = r.revision (+)
AND r.handle = rs.router_bo (+)
AND rs.handle = ro.router_step_bo (+)
AND substr( ro.operation_bo,1,length(ro.operation_bo)-2) = substr( base.oHandle,1,length(base.oHandle)-2)
AND base.operation = cf.operation (+)
AND base.work_center = ''' + #wc2 + '''
)
WHERE rownumber = 1
)
WHERE rep_op_seq = max_wc_op_rpt_seq
ORDER BY shop_order, work_center'
SET #openQueryStr = N'select * into ##tmp_tbl FROM OPENQUERY(WIP, ''' + REPLACE(#sqlStr, '''', '''''') + ''')'
EXEC(#openQueryStr)
--print #sqlStr
UPDATE goal
SET early_actual_yield_to_need_date = t.wc_outs
FROM goal g inner join ##tmp_tbl t ON g.shop_order = t.shop_order
AND g.work_center = Right(t.work_center, LEN(t.work_center)-4)
AND g.early_goal_date = t.goal_date
END
---------------------------------------------------------------------------------------------------------
IF OBJECT_ID('tempdb..##tmp_tbl') IS NOT NULL
DROP TABLE ##tmp_tbl
FETCH NEXT FROM db_cursor INTO #so, #wc, #goalDate, #goal_yield, #early_goal_yield, #early_goal_date
END
CLOSE db_cursor
DEALLOCATE db_cursor
END
END
--[sp_GetGoaling_Outs] 'OR01'
The name ##tmp_tbl is too generic for a Global Temp table, there is probably another process on the server that is using the same name and occasionally overlapping with your process.
Try renaming the ## table to something that is specific to your process
i.e ##tmp_sp_GetGoaling_Outs
If you absolutely want that table dropped before beginning the sp--
BEGIN TRY
drop table ##tmp_tbl
END TRY
BEGIN CATCH
/* table does not exist */
END CATCH
I understand that you need to use global temp table because you are creating it inside a dynamic sql. But I notice that you are creating and dropping the ##tmp_tbl inside a cursor.
I would recommend that you create this global temp table outside of the cursor, such as the following
if object_id('tempdb..##temp_tbl') is not null
drop table ##temp_tbl;
create table ##temp_tbl (....)
Inside your cursor, you need to re-write your dynamic query, instead of using
select .. into ##temp_tbl from ...
using
truncate table ##temp_tbl;
insert into ##temp_tbl (...)
select ... from
I suspect the error you see is probably inside the cursor when trying to do the select * into ##temp_tbl.

Stored procedure passing like statement in case

ALTER PROCEDURE [dbo].[ViewSo]
#Dt1 as datetime,
#Dt2 as datetime,
#CusName as nvarchar,
#so_no as nvarchar
AS
BEGIN
SET NOCOUNT ON;
SELECT *
FROM
(SELECT
0 as stat,
m.id, f.id as fg_id, f.fg_des, m.so_no,
Replace(CONVERT(NVARCHAR, CAST(m.so_date AS DATE) , 106),' ','-') AS so_date,
Convert(NVARCHAR,CAST(m.so_date AS DATE),101) AS so_date1,
m.cus_name, m.so_cus_id, m.doc_no, m.sale_person, m.so_rem,
f.fg_des AS eXP1, f.fg_qty,
CONVERT(VARCHAR(10), CAST(f.req_date AS DATE), 101) AS req_date,
CASE
WHEN COALESCE (q.tot_req_qty, 0) < f.fg_qty
THEN 'Not Updated'
ELSE 'Updated'
END AS req_qty_stat,
'SO No :' + CONVERT(varchar(15), m.so_no) + '/SO Date :' + CONVERT(varchar(15), REPLACE(CONVERT(NVARCHAR, CAST(m.so_date AS DATE), 106), ' ', '-')) + '/Cus Name :' + CONVERT(varchar(15), m.cus_name) + '/Sales Prsn :' + CONVERT(varchar(15), m.sale_person) AS filter ,
f.fg_no,m.so_stat,
m.del_flag, m.st_stat, m.st_rem
FROM
so_mas AS m
INNER JOIN
so_fg AS f ON m.id = f.so_id
LEFT OUTER JOIN
(SELECT
fg_id, SUM(req_qty) AS tot_req_qty
FROM
fg_qty
WHERE
(del_flag = 0)
GROUP BY fg_id) AS q ON q.fg_id = f.id
WHERE
m.del_flag = 0) AS S
WHERE
CONVERT(datetime, s.so_date) BETWEEN #Dt1 AND #Dt2
AND S.cus_name LIKE
CASE WHEN #CusName = '' THEN S.cus_name
ELSE +'%' + #CusName + '%'
END
ORDER BY
s.so_date;
END
This is my stored procedure passing like statement in case. If run as query it works fine. If I used as stored produce leads to wrong result.
Please help me to solve.
Replace this part of WHERE
AND S.cus_name LIKE
CASE WHEN #CusName = '' THEN S.cus_name
ELSE +'%' + #CusName + '%'
END
With
AND S.cus_name LIKE
CASE WHEN #CusName = '' THEN S.cus_name
ELSE '%' + #CusName + '%'
END

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

transform sql query to oracle

i have to transform some query i´m using in SQL to Oracle code. I´m having a lot of trouble with tis. Does anyone know any Query transformer o something like that?. Can someone translate some part of this code for me?.
This is the code:
SELECT PRUEBA = CASE (SELECT TIMEATT FROM READER WHERE PANELID = DEVID AND READERID =
MACHINE) WHEN '1' THEN 'P10' ELSE 'P20' END
+ '0001'
+ CAST(YEAR(EVENT_TIME_UTC)AS VARCHAR)
+ Right('0' + Convert(VarChar(2), Month(EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DAY(EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(HOUR,EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(MINUTE,EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(SECOND,EVENT_TIME_UTC)), 2)
+ CAST(YEAR(EVENT_TIME_UTC)AS VARCHAR)
+ Right('0' + Convert(VarChar(2), Month(EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DAY(EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(HOUR,EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(MINUTE,EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(SECOND,EVENT_TIME_UTC)), 2)
+ Right('00000000' + Convert(VarChar(8), CARDNUM), 8)
+ Right('00000000' + Convert(VarChar(8), (SELECT SSNO FROM EMP WHERE ID = EMPID)), 8),
FROM events
WHERE eventid = 0 AND eventid = 0
and machine in (11) AND DEVID IN (1,2)
and CARDNUM <> 0 AND EMPID <> 0
and EVENT_TIME_UTC between '2006-02-16' AND '2007-02-09'
Many thanks for your help, i´ll keep looking.
Try this:
SELECT CASE (SELECT timeatt FROM reader WHERE panelid = devid AND readerid =
machine)
WHEN '1' THEN 'P10'
ELSE 'P20'
END
|| '0001'
|| To_char(event_time_utc, 'RRRRMMDDHH24MISS')
|| To_char(event_time_utc, 'RRRRMMDDHH24MISS')
|| Lpad(cardnum, 8, '0')
|| Lpad((SELECT ssno
FROM emp
WHERE id = empid), 8, '0') AS prueba
FROM events
WHERE eventid = 0
AND eventid = 0
AND machine IN ( 11 )
AND devid IN ( 1, 2 )
AND cardnum <> 0
AND empid <> 0
AND event_time_utc BETWEEN TO_DATE('2006-02-16', 'RRRR-MM-DD') AND TO_DATE('2007-02-09', 'RRRR-MM-DD')
I have recently had to make the same conversion from a life in tSQL to plSQL (oracle). A couple of "gotcha's" in the code you posted:
1) In tSQL the plus sign (for concatenation)+ is replaced in plSQL with double pipe ||
2) Most of the time you need a "Reference Cursor" (REF CURSOR) declared to put your results into like
PROCEDURE DEMO_SELECT_4_SO(
//other parameters followed by//
P_RESULT OUT REF CURSOR)
IS
BEGIN
OPEN P_RESULT FOR
SELECT
//fields///
FROM
a_table
WHERE
//you want..//
OR (as with a scalar result like your query) a single parameter of the correct type, like:
PROCEDURE DEMO_SELECT_4_SO(
//other parameters followed by//
P_RESULT OUT varchar2(60))
IS
BEGIN
SELECT
//concatenated fields///
INTO
P_RESULT
FROM
a_table
WHERE
//you want..//
NOTICE That select into in plSQL assigns the selected value to the target parameter and does not create a table as it would in tSQL
3) RIGHT (or LEFT) are SUBSTR functions in plSQL
I have found a lot of utility out of this link http://www.techonthenet.com/oracle/index.php for clear explanations of plSQL.