Shorten SQL statement not using a common table expression - sql

The SQL below is written to return 'open orders'. This was written in a way I could understand but now I would like to try and optimize this and reduce the amount of code.
The SQL below gives me the desired outcome I'm looking for however, I would like to shorten the query without using WITH AS. Any suggestions using UNION or some other nesting method?
WITH
product AS --filter by dept
(SELECT item
, dept
FROM item_master
WHERE dept in ('353')
),
open_orders AS --view of orders in Status A with ordered units > received units
(SELECT ol.order_no
, ol.item
, ol.location
, oh.po_type
, oh.order_type
, oh.not_before_date
, oh.not_after_date
, oh.otb_eow_date
, SUM(ol.qty_ordered) AS qty_ordered
, SUM(NVL(ol.qty_received,0)) AS qty_received
FROM ordhead oh
, ordloc ol
WHERE oh.order_no = ol.order_no
AND oh.status = 'A'
AND ol.qty_ordered > NVL(ol.qty_received,0)
-- AND ol.order_no in ('18701212') --optional filter for specific PO's
GROUP BY ol.order_no
, ol.item
, ol.location
, oh.po_type
, oh.order_type
, oh.not_before_date
, oh.not_after_date
, oh.otb_eow_date
),
allocations AS --view of all allocations
(SELECT ah.alloc_no
, ah.order_no
, ah.item
, ad.to_loc
, NVL(ad.qty_allocated,0) AS qty_allocated
, NVL(ad.qty_received,0) AS qty_received
FROM alloc_header ah
, alloc_detail ad
WHERE ah.alloc_no = ad.alloc_no
)
SELECT p.dept --main query on above views
, oo.order_no
, oo.po_type
, oo.order_type
, oo.not_before_date
, oo.not_after_date
, oo.otb_eow_date
, oo.item
, CASE WHEN oo.po_type = 0 THEN oo.location ELSE aa.to_loc END AS loc
, SUM(oo.qty_ordered) AS order_qty
, CASE WHEN SUM(NVL(aa.qty_allocated,0)) - SUM(NVL(aa.qty_received,0)) = 0
THEN SUM(oo.qty_ordered) - SUM(NVL(oo.qty_received,0))
ELSE SUM(NVL(aa.qty_allocated,0)) - SUM(NVL(aa.qty_received,0))
END AS open_qty
FROM open_orders oo
, allocations aa
, product p
WHERE oo.order_no = aa.order_no(+)
AND oo.item = aa.item(+)
AND oo.item = p.item
AND (oo.qty_ordered - oo.qty_received) >0
GROUP BY p.dept
, oo.order_no
, oo.po_type
, oo.order_type
, oo.not_before_date
, oo.not_after_date
, oo.otb_eow_date
, oo.item
, CASE WHEN oo.po_type = 0 THEN oo.location ELSE aa.to_loc END
;

CTE's (Common Table Expressions) are just a way of organizing a query by sticking bits of code (that define a "derived" table) at the top that can be reused in the main statement. As such, where product, open_orders, and allocations are mentioned in the FROM clause, you can just swap those words out with the code that defines them:
SELECT p.dept --main query on above views
,
oo.order_no,
oo.po_type,
oo.order_type,
oo.not_before_date,
oo.not_after_date,
oo.otb_eow_date,
oo.item,
CASE
WHEN oo.po_type = 0
THEN oo.location
ELSE aa.to_loc
END AS loc,
SUM(oo.qty_ordered) AS order_qty,
CASE
WHEN SUM(NVL(aa.qty_allocated, 0)) - SUM(NVL(aa.qty_received, 0)) = 0
THEN SUM(oo.qty_ordered) - SUM(NVL(oo.qty_received, 0))
ELSE SUM(NVL(aa.qty_allocated, 0)) - SUM(NVL(aa.qty_received, 0))
END AS open_qty
FROM (
SELECT ol.order_no,
ol.item,
ol.location,
oh.po_type,
oh.order_type,
oh.not_before_date,
oh.not_after_date,
oh.otb_eow_date,
SUM(ol.qty_ordered) AS qty_ordered,
SUM(NVL(ol.qty_received, 0)) AS qty_received
FROM ordhead oh,
ordloc ol
WHERE oh.order_no = ol.order_no
AND oh.STATUS = 'A'
AND ol.qty_ordered > NVL(ol.qty_received, 0)
-- AND ol.order_no in ('18701212') --optional filter for specific PO's
GROUP BY ol.order_no,
ol.item,
ol.location,
oh.po_type,
oh.order_type,
oh.not_before_date,
oh.not_after_date,
oh.otb_eow_date
) oo,
(
SELECT ah.alloc_no,
ah.order_no,
ah.item,
ad.to_loc,
NVL(ad.qty_allocated, 0) AS qty_allocated,
NVL(ad.qty_received, 0) AS qty_received
FROM alloc_header ah,
alloc_detail ad
WHERE ah.alloc_no = ad.alloc_no
) aa,
(
SELECT item,
dept
FROM item_master
WHERE dept IN ('353')
) p
WHERE oo.order_no = aa.order_no(+)
AND oo.item = aa.item(+)
AND oo.item = p.item
AND (oo.qty_ordered - oo.qty_received) > 0
GROUP BY p.dept,
oo.order_no,
oo.po_type,
oo.order_type,
oo.not_before_date,
oo.not_after_date,
oo.otb_eow_date,
oo.item,
CASE
WHEN oo.po_type = 0
THEN oo.location
ELSE aa.to_loc
END;
This is obviously not shortened (but by a few characters), but I get the sense that "shortening" isn't your requirement. You are trying to get this query to work in a product that doesn't support CTEs.

Related

Performance issue using IsNull function in the Select statement

I have a financial application. I have ViewHistoricInstrumentValue which has rows like this
instrument1, date1, price, grossValue, netValue
instrument2, date1, price, grossValue, netValue
...
instrument1, date2, price, grossValue, netValue
...
My views are complicated but the db itself is small (4000 transactions). ViewHistoricInstrumentValue was executed in less than 1 second before I added the next CTE to the view. After that it takes 26s. ActualEvaluationPrice is the price for instrumentX at dateY. If this value is missing from HistoricPrice table then I find the previous price for instrumentX.
, UsedEvaluationPriceCte AS (
SELECT *
, isnull(ActualEvaluationPrice,
(select top 1 HistoricPrice.Price -- PreviousPrice
from HistoricPrice JOIN ValidDate
on HistoricPrice.DateId = ValidDate.Id
and HistoricPrice.InstrumentId = StartingCte.InstrumentId
and ValidDate.[Date] < StartingCte.DateValue
order by ValidDate.[Date]))
as UsedEvaluationPrice
FROM StartingCte
)
My problem is that the execution time increased needlessly. Right now the HistoricPrice table has no missing value so ActualEvaluationPrice is never null, so the previous price should be never determined.
ViewHistoricInstrumentValue returns 1815 rows. One other mystery is that the first query takes 26s, but the second only 2s.
SELECT * FROM [ViewHistoricInstrumentValue]
SELECT top(2000) * FROM [ViewHistoricInstrumentValue]
Appendix
The execution plan: https://www.dropbox.com/s/5st69uhjkpd3b5y/IsNull.sqlplan?dl=0
The same plan: https://www.brentozar.com/pastetheplan/?id=rk9bK1Wiv
The view:
ALTER VIEW [dbo].[ViewHistoricInstrumentValue] AS
WITH StartingCte AS (
SELECT
HistoricInstrumentValue.DateId
, ValidDate.Date as DateValue
, TransactionId
, TransactionId AS [Row]
, AccountId
, AccountName
, ViewTransaction.InstrumentId
, ViewTransaction.InstrumentName
, OpeningDate
, OpeningPrice
, Price AS ActualEvaluationPrice
, ClosingDate
, Amount
, isnull(ViewTransaction.FeeValue, 0) as FeeValue
, HistoricInstrumentValue.Id AS Id
FROM ViewBriefHistoricInstrumentValue as HistoricInstrumentValue
JOIN ValidDate on HistoricInstrumentValue.DateId = ValidDate.Id
JOIN ViewTransaction ON ViewTransaction.Id = HistoricInstrumentValue.TransactionId
left JOIN ViewHistoricPrice ON ViewHistoricPrice.DateId = HistoricInstrumentValue.DateId AND
ViewHistoricPrice.InstrumentId = ViewTransaction.InstrumentId
)
, UsedEvaluationPriceCte AS (
SELECT *
, isnull(ActualEvaluationPrice,
(select top 1 HistoricPrice.Price -- PreviousPrice
from HistoricPrice JOIN ValidDate
on HistoricPrice.DateId = ValidDate.Id
and HistoricPrice.InstrumentId = StartingCte.InstrumentId
and ValidDate.[Date] < StartingCte.DateValue
order by ValidDate.[Date]))
as UsedEvaluationPrice
FROM StartingCte
)
, GrossEvaluationValueCte AS (
SELECT *
, Amount * UsedEvaluationPrice AS GrossEvaluationValue
, (UsedEvaluationPrice - OpeningPrice) * Amount AS GrossCapitalGains
FROM UsedEvaluationPriceCte
)
, CapitalGainsTaxCte AS (
SELECT *
, dbo.MyMax(GrossCapitalGains * 0.15, 0) AS CapitalGainsTax
FROM GrossEvaluationValueCte
)
, IsOpenCte AS (
SELECT
DateId
, DateValue
, TransactionId
, [Row]
, AccountId
, AccountName
, InstrumentId
, InstrumentName
, OpeningDate
, OpeningPrice
, ActualEvaluationPrice
, UsedEvaluationPrice
, ClosingDate
, Amount
, GrossEvaluationValue
, GrossCapitalGains
, CapitalGainsTax
, FeeValue
, GrossEvaluationValue - CapitalGainsTax - FeeValue AS NetEvaluationValue
, GrossCapitalGains - CapitalGainsTax - FeeValue AS NetUnrealizedGains
, CASE WHEN ClosingDate IS NULL OR DateValue < ClosingDate
THEN CAST(1 AS BIT)
ELSE CAST(0 AS BIT)
END
AS IsOpen
, convert(NVARCHAR, DateValue, 20) + cast([Id] AS NVARCHAR(MAX)) AS Temp
, Id
FROM CapitalGainsTaxCte
)
Select * from IsOpenCte
I have no idea what your query is supposed to be doing. But this process:
ActualEvaluationPrice is the price for instrumentX at dateY. If this value is missing from HistoricPrice table then I find the previous price for instrumentX.
is handled easily with lag():
select vhiv.*
coalesce(vhiv.ActualEvaluationPrice,
lag(vhiv.ActualEvaluationPrice) over (partition by vhiv.InstrumentId order by DateValue)
) as UsedEvaluationPrice
from ViewHistoricInstrumentValue vhiv;
Note: If you need to filter out certain dates by joining to ValidDates, you can include the JOIN in the query. However, that is not part of the problem statement.

The query I ran returns 2 of the same column which isn't allowed in tableau and I can't fix the query

I need to be able to get rid of one of the workdate and one of the sr_name columns but I can't figure out how to.
I'm getting the query returned like this:
Query
I'm also getting this error message when entered into tableau:
The column 'sr_name' was specified multiple times for 'Custom SQL Query'.
Below is the code I have. If I remove a sr_name from either subquery there will be an error in the join clause.
select *
from
(
select s.sr_name, cast(punchdatetime as date) as workdate,
((datediff(second, min(case when p.InOut = 1 then punchdatetime end),
max(case when p.InOut = 0 then punchdatetime end))/3600) - .5) as
hoursworked
from PunchClock p join ServiceReps s on p.ServRepID = s.ServRepID
where punchyear >= 2019
group by s.sr_name, cast(punchdatetime as date)
) v
join
(
select sr_name, t.*,
calls = (select count(*) from CRM_Correspondence cr where
cast(cr.DateCreated as date) = workdate and StatusType like '%call%' and
cr.ServRepID = t.servrepid),
reaches = (select count(*) from CRM_Correspondence cr where
cast(cr.DateCreated as date) = workdate and (StatusType = 'call reached'
or StatusType like '%SCHEDULE%') and cr.ServRepID = t.servrepid),
books = (select count(*) from os_appointments o where cast(o.DateCreated
as date) = workdate and isnull(o.confirmedby, o.booked_by) =
t.servrepid),
attends = (select count(*) from os_appointments o where
cast(o.DateCreated as date) = workdate and isnull(o.confirmedby,
o.booked_by) = t.servrepid and o.appointmentStatus = 'attended')
from
(
select cast(cor.datecreated as date) workdate, cor.ServRepID
from CRM_Correspondence cor
where cor.datecreated > '2019-01-01'
group by cast(cor.datecreated as date), cor.servrepid
) t
join ServiceReps sr on t.ServRepID = sr.ServRepID
) u on v.sr_name = u.sr_name and v.workdate = u.workdate
I need the same results just without the duplicate column so I can enter the query into tableau.
This is challenging because you have so many subqueries here. This could be refactored to use a single query which is what I would do. But using the existing query you could do something along these lines.
I had to format this very differently so I could isolate each piece.
select v.sr_name
, v.workdate
, v.hoursworked
, u.ServRepID
, u.calls
, u.reaches
, u.books
, u.attends
from
(
select s.sr_name
, cast(punchdatetime as date) as workdate
, ((datediff(second, min(case when p.InOut = 1 then punchdatetime end), max(case when p.InOut = 0 then punchdatetime end))/3600) - .5) as hoursworked
from PunchClock p
join ServiceReps s on p.ServRepID = s.ServRepID
where punchyear >= 2019
group by s.sr_name
, cast(punchdatetime as date)
) v
join
(
select sr_name
, t.*
, calls =
(
select count(*)
from CRM_Correspondence cr
where cast(cr.DateCreated as date) = workdate
and StatusType like '%call%'
and cr.ServRepID = t.servrepid
)
, reaches =
(
select count(*)
from CRM_Correspondence cr
where cast(cr.DateCreated as date) = workdate
and (StatusType = 'call reached' or StatusType like '%SCHEDULE%')
and cr.ServRepID = t.servrepid
)
, books =
(
select count(*)
from os_appointments o
where cast(o.DateCreated as date) = workdate and isnull(o.confirmedby, o.booked_by) = t.servrepid
)
, attends =
(
select count(*)
from os_appointments o
where cast(o.DateCreated as date) = workdate
and isnull(o.confirmedby, o.booked_by) = t.servrepid
and o.appointmentStatus = 'attended'
)
from
(
select cast(cor.datecreated as date) workdate
, cor.ServRepID
from CRM_Correspondence cor
where cor.datecreated > '2019-01-01'
group by cast(cor.datecreated as date)
, cor.servrepid
) t
join ServiceReps sr on t.ServRepID = sr.ServRepID
) u on v.sr_name = u.sr_name
and v.workdate = u.workdate

Remove rows where one row offsets the next using accounting rules

I have a view of materials data which contains what was purchased and reversals of some of the purchases. I need a query that removes records that have reversals of purchase transactions. NOTE: The view does not have a primary key.
In the example I need to remove the first two rows as the second row offsets the first row because it reverses the purchase, but I need to keep the third row. Any ideas?
Here is the SQL for the view:
SELECT LEFT(mi.Plnt, 3) AS SBUID ,
oth.EQUIP AS PROJECTID ,
ms.Req_No AS GI ,
ms.Req_Item AS GI_LINE ,
CONVERT(VARCHAR(11), [Doc_Date], 100) + ' 12:00 AM' AS DOC_DATE ,
mi.[SLoc] AS SLOC ,
[Material] AS MATERIAL ,
mi.[Description] AS MATERIAL_DESCRIPTION ,
[Qty] AS QUANTITY ,
mi.[UoM] AS UOM ,
CASE WHEN mi.Mvt IN ( '101', '103', '105', '123', '261' ) THEN
mi.Amount
ELSE mi.Amount * -1
END AS Cost ,
mi.Amount AS EXT_ORG_COST ,
mi.PO AS [PO] ,
mi.Batch ,
mi.Vendor AS VENDOR ,
mi.VendorName AS VENDOR_NAME ,
at.AC_Group AS AC_TYPE ,
[Mvt] AS MVT
FROM [dbo].[MatIssued] mi
INNER JOIN dbo.OrderTableHistory oth ON oth.SUB_ORDER = mi.SubOrder
INNER JOIN dbo.Aircraft_Information2 ai ON ai.Equip = oth.EQUIP
INNER JOIN dbo.RFC_AcftTypeList at ON at.ID = ai.AC_TypeID
LEFT OUTER JOIN dbo.MatStatus ms ON ms.MPN = mi.Material
AND ms.SubOrder = mi.SubOrder
WHERE mi.Plnt IN ( '9131', '9132' )
AND mi.Mvt IN ( '101', '102', '103', '104', '105', '106', '122', '123' ,
'261' ,'262' )
AND mi.Doc_Date >= DATEADD(YEAR, -1, GETDATE())
ORDER BY mi.PO ,
mi.Batch ,
PROJECTID ,
mi.Mvt;
Some assumptions, based on your screenshot:
Reversals have same DOC_DATE as purchases
Reversals have same Batch as purchases
If the above assumptions are correct, try something like this:
DELETE FROM t
FROM MyTable t
WHERE EXISTS (
SELECT 1
FROM MyTable t2
WHERE
-- Join to outer table
t2.SLOC = t.SLOC
AND t2.MATERIAL = t.MATERIAL
AND t2.QUANTITY = t.QUANTITY
AND t2.PO = t.PO
AND t2.Batch = t.Batch
AND t2.VENDOR = t.VENDOR
GROUP BY SLOC, MATERIAL, QUANTITY, PO, Batch, VENDOR
HAVING COUNT(*) = 2 -- There are 2 matching rows
AND -MIN(QUANTITY) = MAX(QUANTITY) -- Minimum quantity negates Maximum quantity
AND MIN(COST) + MAX(COST) = 0 -- Costs cancel each other out
AND MIN(CASE WHEN Cost > 0 THEN DOC_DATE END) <= MIN(CASE WHEN Cost < 0 THEN DOC_DATE END) -- Purchase DOC_DATE less than or equal to reversal DOC_DATE
AND MIN(MVT) = MAX(MVT) + 1 -- Correlate purchase and reversal movement
AND (t.DOC_DATE = MIN(DOC_DATE) OR t.DOC_DATE = MAX(DOC_DATE)) -- Join to outer table
)

How can I change these into columns?

I've tried using CTE, but haven't been able to figure it out. I want to change the multiple rows into one row with multiple columns going accross. Any way to go about this...
Current Result
ern CostPool
111 NULL
111 5
Desired Result
ern CostPool1 CostPool2
111 NULL 5
SELECT first_name, last_name, ern, pc, title, TitleDesc, OfficeTitle, SUM(earned) earned, fypaydate, q
, [RMTS, Support, or Partial Quarter], SUM(CAST([Staff Employment Status] AS INT)) sumEmpStatus, SUM(CAST(countisMHy AS INT)) sumcountisMHy, SUM(CAST(sumisMHy AS INT)) sumisMHy1
, SUM(CAST(sumEligible AS INT)) sumEligible1
, CostPool
FROM (
SELECT
e.first_name, e.last_name
, fss.ern
, fss.pc
, fss4.title
, u.OfficeTitle
, t.TitleDesc
, SUM(fss.gross*fss.[percent]) earned
, fss.fypaydate, fss.q
, cpayfss3, cpaypdq
, CASE WHEN cpayfss3 = cpaypdq THEN '1' --full q
WHEN cpayfss3 < cpaypdq THEN '2' --part q
ELSE 'Check'
END [RMTS, Support, or Partial Quarter]
, CASE WHEN COUNT(DISTINCT rc.isMHy) = 2 THEN '9' --split
WHEN fss.pc = 'A' AND COUNT(DISTINCT rc.isMHy) = 1 AND SUM(CAST(rc.isMHy AS INT)) > 0 THEN '1' --full
WHEN fss.pc IN ('X', 'O', 'W', 'L', 'K') AND SUM(CAST(rc.isMHy AS INT)) > 0 THEN '2' --part
ELSE '0'
END [Staff Employment Status]
, COUNT(DISTINCT rc.isMHy) countisMHy
, SUM(CAST(rc.isMHy AS INT)) sumisMHy
, SUM(CAST(rc.Eligible AS INT)) sumEligible --count distinct too?
, rc.CostPool
FROM [FIN_DataMart].[dbo].[FSSpaydetl_NEW] fss
LEFT JOIN FIN_DataMart.[dbo].[FSSRC_NEW] rc
ON fss.newrc = rc.RC
AND fss.fypaydate = rc.FY
INNER JOIN
(
SELECT ern, fypaydate, q, COUNT(DISTINCT paydate) cpayfss3
FROM [FIN_DataMart].[dbo].[FSSpaydetl_NEW]
GROUP BY fypaydate, q, ern
) fss3
ON fss.ern = fss3.ern
AND fss.fypaydate = fss3.fypaydate
AND fss.q = fss3.q
LEFT JOIN
(
SELECT COUNT(DISTINCT paydate) cpaypdq, fy, q
FROM [FIN_DataMart].[dbo].[FSSPayDateQ]
GROUP BY fy, q
) pdq
ON fss.fypaydate = pdq.fy
AND fss.q = pdq.q
LEFT JOIN
[FIN_DataMart].[dbo].FSSEmployeeInfo e
ON fss.ern = e.ern
INNER JOIN
(
SELECT DISTINCT ern, title, tlvl, fy, q, ROW_NUMBER() OVER (PARTITION BY ern, fy, q ORDER BY title DESC) rn
FROM [FIN_DataMart].[dbo].[FSSpaydetl_NEW]
) fss4
ON fss.ern = fss4.ern
AND fss.fypaydate = fss4.fy
AND fss.q = fss4.q
AND fss4.rn = '1'
LEFT JOIN
(
SELECT TCode, TLevel, GenericTDesc as TitleDesc, EED,
ROW_NUMBER() OVER (PARTITION BY TCode, TLevel ORDER BY EED DESC) rn
FROM [FIN_DataMart].[dbo].FSATitle
) t
ON fss4.title = t.TCode
AND case when fss4.tlvl = '' THEN '01' WHEN fss4.tlvl IS NULL THEN '01' ELSE fss4.tlvl END = t.TLevel
AND t.rn = 1
LEFT JOIN FIN_DataMart.[dbo].[FSSUserERN] u
ON fss.ern = u.ern
WHERE fss.fypaydate = 2015
AND fss.q = 1
AND fss.obj <> '049' AND fss.obj NOT LIKE 'x%'
AND fss.title NOT IN ('10209', '1020B', '10234', '10232', '20202', '21205', '30086', '34201')
GROUP BY
fss.ern
, fss.pc
, fss4.title
, fss.fypaydate, fss.q
, cpayfss3, cpaypdq
, rc.CostPool
, t.TitleDesc
, e.first_name
, e.last_name
, u.OfficeTitle
HAVING SUM(CAST(rc.Eligible AS INT)) >=1
) A
GROUP BY
first_name, last_name, ern, pc, title, fypaydate, q
, [RMTS, Support, or Partial Quarter]
, OfficeTitle
, TitleDesc
, CostPool
ORDER BY first_name, last_name, fypaydate, q
You can look into using the Pivot operator to convert your rows into columns.
https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
That method would work, although your sample data and expected result do not quite match the massive query you have posted so I cannot provide a more specific example until you provide more test data/expected outputs (and table schema).

recursive common table expression with a view

This is what Im trying to do:
Create view vDetailsCommunications as
WITH Tickets AS
(
SELECT CallLog.CallID
, CallLog.RecvdDate
, Detail.ReqEffDate
, Asgnmnt.DateAcknow
, Asgnmnt.DateResolv
, Asgnmnt.Assignee
, Asgnmnt.GroupName
, CallLog.CallType
, Detail.ActionReq
, Detail.action_type
, (SELECT [Days] FROM NonWorkingDays(Asgnmnt.DateAcknow, Asgnmnt.DateResolv) AS NonWorkingDays_1) AS [Working Days]
, DATEDIFF(day, Asgnmnt.DateAcknow, Asgnmnt.DateResolv) AS [Days]
, (ROW_NUMBER() OVER(PARTITION BY Asgnmnt.CallID ORDER BY Asgnmnt.DateAcknow)) AS [Row Number]
FROM CallLog
INNER JOIN Detail ON CallLog.CallID = Detail.CallID
INNER JOIN Asgnmnt ON CallLog.CallID = Asgnmnt.CallID
WHERE (CallLog.CallType = 'ID Request-PAF')
AND (Detail.ActionReq = 'Hiring Action')
AND (DATEDIFF (DAY, Asgnmnt.DateAcknow, Asgnmnt.DateResolv) BETWEEN 0 AND 99)
AND (Asgnmnt.GroupName IN ('ID Admin', 'Systems Admin'))
AND (Detail.action_type IN ('Applicant Hire', 'Re-Hire'))
)
SELECT *
FROM Tickets
WHERE [Row Number] = 1
you need to define a schema in this function: NonWorkingDays.
ex:
SELECT [Days] FROM dbo.NonWorkingDays(Asgnmnt.DateAcknow, Asgnmnt.DateResolv)