CTE TABLE WITH ORDER BY ERROR MESSAGE SQL SERVER - sql

;WITH myTree AS
(
SELECT
y.User_id, y.user_usercode, y.user_username,
y.user_uplineID,
trans_WinLose, y.User_ID AS sourceID, trans_id,
trans_Rolling, y.User_Level,
lvl1.User_Level AS Level_lvl1, lvl2.User_Level AS Level_lvl2,
y.User_GivenPT, lvl1.User_GivenPT AS GivenPT_lvl1,
lvl2.User_GivenPT AS GivenPT_lvl2, y.User_GivenComm,
lvl1.User_GivenComm AS downline_Comm
FROM
tbl_user y
INNER JOIN
tbl_trans x ON x.trans_Robot_ID = y.User_RobotID
INNER JOIN
tbl_user lvl1 ON y.user_uplineID = lvl1.User_ID
INNER JOIN
tbl_user lvl2 ON lvl1.user_uplineID = lvl2.User_ID
UNION ALL
SELECT
u.User_ID, u.user_usercode, u.user_username, u.user_uplineID,
t.trans_WinLose, t.sourceID AS sourceID, t.trans_Id,
t.trans_Rolling, u.User_Level, t.User_Level, t.Level_lvl1,
u.User_GivenPT, t.User_GivenPT, t.GivenPT_lvl1,
u.User_GivenComm, t.User_GivenComm
FROM
myTree t
INNER JOIN
tbl_user u ON t.user_uplineID = u.User_ID
)
SELECT *
FROM
(SELECT
mytree.*,
(SELECT
CASE
WHEN Level_lvl1 = 7 THEN GivenPT_lvl1
WHEN level_lvl2 = 7 THEN User_GivenPT-GivenPT_Lvl2
ELSE (CASE
WHEN (User_GivenPT-GivenPT_lvl1) > 0
THEN User_GivenPT - GivenPT_lvl1
ELSE 0
END)
END) AS Net_PT
FROM
Mytree
ORDER BY
mytree.trans_ID) AS c
I would like to order by mytree.trans_ID, but I get an error:
Msg 1033, Level 15, State 1, Line 17
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
How to solve this problem?

Another possibility is to remove the outer query when querying the CTE - it doesn't seem to serve any purpose.
;with myTree as (
select y.User_id,y.user_usercode,y.user_username,y.user_uplineID,trans_WinLose, y.User_ID as sourceID, trans_id,trans_Rolling,y.User_Level,lvl1.User_Level as Level_lvl1,lvl2.User_Level as Level_lvl2,y.User_GivenPT,lvl1.User_GivenPT as GivenPT_lvl1 ,lvl2.User_GivenPT as GivenPT_lvl2,y.User_GivenComm,lvl1.User_GivenComm as downline_Comm from tbl_user y
Inner join tbl_trans x on x.trans_Robot_ID = y.User_RobotID
Inner join tbl_user lvl1 on y.user_uplineID = lvl1.User_ID
Inner join tbl_user lvl2 on lvl1.user_uplineID = lvl2.User_ID
union all
select u.User_ID,u.user_usercode,u.user_username,u.user_uplineID,t.trans_WinLose, t.sourceID as sourceID, t.trans_Id,t.trans_Rolling,u.User_Level,t.User_Level,t.Level_lvl1,u.User_GivenPT,t.User_GivenPT,t.GivenPT_lvl1,u.User_GivenComm,t.User_GivenComm
from myTree t
inner join tbl_user u on t.user_uplineID = u.User_ID
)
SELECT mytree.*,
(SELECT CASE
WHEN Level_lvl1=7 THEN GivenPT_lvl1
WHEN level_lvl2=7 THEN User_GivenPT-GivenPT_Lvl2
ELSE (CASE WHEN (User_GivenPT-GivenPT_lvl1) > 0 THEN User_GivenPT-GivenPT_lvl1 else 0 END)
END) as Net_PT
From Mytree order by mytree.trans_ID

SQL behaves with data in Mathematics Sets manner. In Sets the order of data and elements are meaningless. So when you are dealing with CTE, sub-queries, views, inline table value functions etc, that are used to return a set of data, you are not allowed to order and sort them.
You need to sort data when you need to show them in output or you are using TOP or OFFSET-Fetch or etc commands, where the Order By helps these commands to work as they should be.
You should rewrite your query as:
;with myTree as (
select y.User_id,y.user_usercode,y.user_username,y.user_uplineID,trans_WinLose, y.User_ID as sourceID, trans_id,trans_Rolling,y.User_Level,lvl1.User_Level as Level_lvl1,lvl2.User_Level as Level_lvl2,y.User_GivenPT,lvl1.User_GivenPT as GivenPT_lvl1 ,lvl2.User_GivenPT as GivenPT_lvl2,y.User_GivenComm,lvl1.User_GivenComm as downline_Comm from tbl_user y
Inner join tbl_trans x on x.trans_Robot_ID = y.User_RobotID
Inner join tbl_user lvl1 on y.user_uplineID = lvl1.User_ID
Inner join tbl_user lvl2 on lvl1.user_uplineID = lvl2.User_ID
union all
select u.User_ID,u.user_usercode,u.user_username,u.user_uplineID,t.trans_WinLose, t.sourceID as sourceID, t.trans_Id,t.trans_Rolling,u.User_Level,t.User_Level,t.Level_lvl1,u.User_GivenPT,t.User_GivenPT,t.GivenPT_lvl1,u.User_GivenComm,t.User_GivenComm
from myTree t
inner join tbl_user u on t.user_uplineID = u.User_ID
)select * from (SELECT mytree.*,
(SELECT CASE
WHEN Level_lvl1=7 THEN GivenPT_lvl1
WHEN level_lvl2=7 THEN User_GivenPT-GivenPT_Lvl2
ELSE (CASE WHEN (User_GivenPT-GivenPT_lvl1) > 0 THEN User_GivenPT-GivenPT_lvl1 else 0 END)
END) as Net_PT
From Mytree) as c
order by c.trans_ID

From Mytree order by mytree.trans_ID OFFSET 0 ROWS
change it to this, solved

Related

Trying to run a query in Information Design Tool in SAP (using mssql database)

WITH c AS
(SELECT A.QuestionHdrKey AS QuestionHdrKey1,
A.DivisionKey AS DivisionKey1,
COUNT(1) AS QCount
FROM Mobile.QuestionLocationMap A WITH (NOLOCK)
INNER JOIN Mobile.Question b WITH (NOLOCK) ON A.QuestionKey = b.PKey
WHERE A.QuestionHdrKey = 200305685377000000
GROUP BY A.QuestionHdrKey,
A.DivisionKey),
d AS
(SELECT a.QuestionHdrKey,
a.QuestionKey,
a.DivisionKey,
a.InvDate,
a.HdrKey,
ROW_NUMBER() OVER (PARTITION BY a.DivisionKey,
a.invdate,
a.HdrKey
ORDER BY a.QuestionKey) AS RowId
FROM mobile.StatusReport a WITH (NOLOCK)
INNER JOIN mobile.Question b WITH (NOLOCK) ON a.QuestionKey = b.PKey
AND b.QuestionType = 'rate'
AND InputType = 'numeric'
WHERE a.QuestionHdrKey = '200305685377000000'
GROUP BY a.QuestionHdrKey,
a.DivisionKey,
a.HdrKey,
a.InvDate,
a.QuestionKey)
SELECT a.DivisionKey,
a.InvDate AS ModifiedDate,
a.QuestionHdrKey,
a.HdrKey,
COUNT(DISTINCT a.QuestionKey) AS QuestionKey,
SUM(CAST(a.Value AS int)) AS value,
SUM(b.Rate) AS RATE
--case when a.invdate between '2020-05-09' and '2022-03-31' then case when then case when cast(Value as int)*5>5 then 5 else cast(Value as int)*5 end else cast(Value as int) end as value,c.QCount
FROM mobile.StatusReport a WITH (NOLOCK)
INNER JOIN mobile.Question b WITH (NOLOCK) ON a.QuestionKey = b.PKey
AND b.QuestionType = 'rate'
AND InputType = 'numeric'
INNER JOIN c WITH (NOLOCK) ON a.DivisionKey = c.DivisionKey1
INNER JOIN d WITH (NOLOCK) ON a.HdrKey = d.HdrKey
AND a.QuestionKey = d.QuestionKey
WHERE a.QuestionHdrKey = '200305685377000000'
--and a.HdrKey='210305757994230000'
AND d.RowId <= c.QCount
GROUP BY a.DivisionKey,
a.InvDate,
a.QuestionHdrKey,
a.HdrKey,
c.QCount;
I have this table queried in PowerBI which generates the below table:
The SQL is validated successfully in Information Design Tool but when trying to view its values, it shows an error in the code. How do I work around this?
Alright, after figuring out that "with as" doesn't work outside of the select function in the IDS, I've ditched the aliases and used sub-queries.
select HdrKey,a.DivisionKey,InvDate,RowId ,count(b.QuestionKey) as QCount,qCOUNT_,[value],POINT
from
(select distinct a.HdrKey,a.DivisionKey, a.InvDate, ROW_NUMBER() OVER(PARTITION BY QuestionHdrKey, DivisionKey, a.InvDate ORDER BY a.InvDate) AS RowId,
sum(cast([value] as int)) AS [value], COUNT(DISTINCT A.QuestionKey) AS qCOUNT_, SUM(B.Rate) AS POINT
from NominInventory.mobile.StatusReport a with(nolock)
inner join NominInventory.mobile.Question b with(nolock) on a.QuestionKey=b.PKey and B.QuestionType = 'rate' and InputType='numeric'
where a.QuestionHdrKey='200305685377000000'
GROUP BY a.HdrKey,a.DivisionKey, a.InvDate,QuestionHdrKey
) a
inner join NominInventory.Mobile.QuestionLocationMap b with(nolock) on a.DivisionKey=b.DivisionKey and b.QuestionHdrKey = '200305685377000000'
group by HdrKey,a.DivisionKey,InvDate,RowId,qCOUNT_,[value],POINT
having a.RowId<=count(b.QuestionKey)

Nesting queries on JOINS and top1 with ties

I am trying to use the result of the below SQL query-1 such that I can make another JOIN on this with my second query result to retrieve Fundsrc on the common ID - Project.
QUERY 1-
SELECT top 1 with ties
t.project, r.rel_value AS "FundSrc" ,r.date_to
from atsproject t
LEFT OUTER JOIN aglrelvalue r ON(t.client=r.client AND r.rel_attr_id='ZB18' AND r.attribute_id='B0' AND t.project=r.att_value)
WHERE r.date_To > '04/30/2020' and status='n'
ORDER BY row_number() over (partition by t.project order by t.project, r.rel_value)
I cannot put the JOIN inside the above query as it will mess with the result. Instead, if I can do a nesting on this then I think that should solve the issue.
My second query is -
SELECT
t.project,t.work_order as activity, r1.labor_funding_source2_fx AS "Designated Labour Funding"
FROM atsworkorder t
LEFT OUTER JOIN afxactlaborfund r1 ON( t.work_order = r1.dim_value AND t.client = r1.client AND r1.attribute_id = 'BF')
WHERE t.client='PC' and t.status = 'N'
The Output should be -
t.project,t.work_order from query 2 + Fundsrc from Query 1, with the common id on Project ID.
Any suggestions on this is highly appreciated.
You can wrap 'subqueries' in parenthesis and then join them.
Can you try this?:
SELECT *
FROM (
SELECT top 1 with ties t.project,
r.rel_value AS "FundSrc",
r.date_to
FROM atsproject t
LEFT OUTER JOIN aglrelvalue r
ON t.client=r.client
AND r.rel_attr_id='ZB18'
AND r.attribute_id='B0'
AND t.project=r.att_value
WHERE r.date_To > '04/30/2020' and status='n'
ORDER BY row_number() over (partition by t.project order by t.project, r.rel_value)
) AS TABLE_1
LEFT JOIN
(
SELECT t.project,
t.work_order as activity,
r1.labor_funding_source2_fx AS "Designated Labour Funding"
FROM atsworkorder t
LEFT OUTER JOIN afxactlaborfund r1
ON t.work_order = r1.dim_value
AND t.client = r1.client
AND r1.attribute_id = 'BF'
WHERE t.client='PC' and t.status = 'N'
) AS TABLE_2
ON TABLE_1.PROJECT = TABLE2.PROJECT
I am pretty sure an ORDER BY clause will not work within a subquery. Thus, this should probably work:
SELECT *
FROM (
SELECT t.project,
r.rel_value AS "FundSrc",
r.date_to,
row_number() over (partition by t.project order by t.project, r.rel_value) AS MY_RANKING
FROM atsproject t
LEFT OUTER JOIN aglrelvalue r
ON t.client=r.client
AND r.rel_attr_id='ZB18'
AND r.attribute_id='B0'
AND t.project=r.att_value
WHERE r.date_To > '04/30/2020' and status='n'
) AS TABLE_1
LEFT JOIN
(
SELECT t.project,
t.work_order as activity,
r1.labor_funding_source2_fx AS "Designated Labour Funding"
FROM atsworkorder t
LEFT OUTER JOIN afxactlaborfund r1
ON t.work_order = r1.dim_value
AND t.client = r1.client
AND r1.attribute_id = 'BF'
WHERE t.client='PC' and t.status = 'N'
) AS TABLE_2
ON TABLE_1.PROJECT = TABLE2.PROJECT
WHERE TABLE_1.MY_RANKING = 1
Note: On your formatting, wrap words within ` when they refer to code. They will look like this.
Wrap blocks of code within three of those (three at the beginning and at the end). It will look like the blocks of code above.

SQL code in Access says error in FROM clause

SELECT
p.Name,
p.Age,
MAX(COUNT(m.winTeam_ID) / (COUNT(m.winTeam_ID) + COUNT(m.lossTeam_ID)))
FROM Players AS p
INNER JOIN Teams AS t
ON t.ID = p.Team_ID
INNER JOIN Matches AS m
ON m.Team_ID = t.ID
GROUP BY
p.Name,
p.Age;
I can suggest the following query:
SELECT TOP 1
p.Name,
p.Age,
COUNT(m.winTeam_ID) / (COUNT(m.winTeam_ID) + COUNT(m.lossTeam_ID))
FROM (Players AS p
INNER JOIN Teams AS t
ON t.ID = p.Team_ID)
INNER JOIN Matches AS m
ON m.Team_ID = t.ID
GROUP BY
p.Name,
p.Age
ORDER BY
COUNT(m.winTeam_ID) / (COUNT(m.winTeam_ID) + COUNT(m.lossTeam_ID)) DESC;
This fixes the syntax problem with your joins. It also interprets the MAX as meaning that you want the record with the maximum ratio of counts. In this case, we can use TOP 1 along with ORDER BY to identify this max record.
MS Access requires strange parentheses when you have more than one join. In addition, MAX(COUNT(m.winTeam_ID)) doesn't make sense. I don't know what you are trying to calculate in the SELECT. Perhaps this does what you want:
SELECT p.Name, p.Age,
COUNT(m.winTeam_ID) / (COUNT(m.winTeam_ID) + COUNT(m.lossTeam_ID)))
FROM (Players AS p INNER JOIN
Teams AS t
ON t.ID = p.Team_ID
) INNER JOIN
Matches AS m
ON m.Team_ID = t.ID
GROUP BY p.Name, p.Age;
I think your Matches table shouldn't have a Team_ID And instead you have winTeam_ID and lossTeam_ID!
And also you want to query players of a team with - something like - the best win-rate.
If so, Use a query like this - tested on SQL Server only -:
select
p.Age, p.Name, ts.rate
from
Players p
join
(select top(1) -- sub-query will return just first record
t.ID
, sum(case when (t.ID = winTeam_ID) then 1 else 0 end) as wins
, sum(case when (t.ID = lossTeam_ID) then 1 else 0 end) as losses
, sum(case when (t.ID = winTeam_ID) then 1.0 else 0.0 end) /
(sum(case when (t.ID = winTeam_ID) then 1.0 else 0.0 end) + sum(case when (t.ID = lossTeam_ID) then 1.0 else 0.0 end)) as rate
from Teams as t
left join Matches as m
on t.ID = m.winTeam_ID
or t.ID = lossTeam_ID
group by t.ID
order by rate desc -- This will make max rate as first
) as ts -- Team stats calculated in this sub-query
on p.Team_ID = ts.ID;

Oracle SQL Correlated subquery - Returning count(*) in some columns

I have my initial statement which is :
SELECT TEAM.ID PKEY_SRC_OBJECT,
TEAM.MODF_DAT UPDATE_DATE,
TEAM.MODF_USR UPDATED_BY,
PERSO.FIRST_NAM FISRT_NAME
FROM TEAM
LEFT OUTER JOIN PERSO ON (TEAM.ID=PERSO.TEAM_ID)
I want to calculate some "flags" and return them in my initial statement.
There are 3 flags which can be calculated like this :
1) Flag ISMASTER:
SELECT Count(*)
FROM TEAM_TEAM_REL A, TEAM B
WHERE B.PARTY_PTY_ID = A.RLTD_TEAM_ID
AND CODE = 'Double';
2) Flag ISAGENT:
SELECT Count(*)
FROM TEAM_ROL_REL A, TEAM B
WHERE B.PARTY_PTY_ID = A.TEAM_ID;
3) Flag NUMPACTS:
SELECT Count(*)
FROM TEAM_ROL_REL A,
TEAM_ROL_POL_REL B,
PERSO_POL_STA_REL C,
TEAM D
WHERE A.ROL_CD IN ('1','2')
AND A.T_ROL_REL_ID = B.P_ROL_REL_ID
AND B.P_POL_ID = C.P_POL_ID
AND C.STA_CD = 'A'
AND D.PARTY_PTY_ID = A.TEAM_ID;
To try to achieve this, I've updated my initial statement like this :
WITH ABC AS (
SELECT TEAM.ID PKEY_SRC_OBJECT,
TEAM.MODF_DAT UPDATE_DATE,
TEAM.MODF_USR UPDATED_BY,
PERSO.FIRST_NAM FISRT_NAME
FROM TEAM
LEFT OUTER JOIN PERSO ON (TEAM.ID=PERSO.TEAM_ID)
)
SELECT ABC.*, MAST.ISMASTER, AGENT.ISAGENT, PACTS.NUMPACTS FROM ABC
LEFT OUTER JOIN (
select
RLTD_TEAM_ID,
Count(RLTD_TEAM_ID) OVER (PARTITION BY RLTD_TEAM_ID) as ISMASTER
FROM TEAM_TEAM_REL
WHERE CODE = 'Double'
) MAST
ON ABC.PKEY_SRC_OBJECT = MAST.RLTD_TEAM_ID
LEFT OUTER JOIN (
select
TEAM_ID,
Count(TEAM_ID) OVER (PARTITION BY TEAM_ID) as ISAGENT
FROM TEAM_ROL_REL
) AGENT
ON ABC.PKEY_SRC_OBJECT = AGENT.TEAM_ID
LEFT OUTER JOIN (
select
TEAM_ID,
Count(TEAM_ID) OVER (PARTITION BY TEAM_ID) as NUMPACTS
FROM TEAM_ROL_REL, TEAM_ROL_POL_REL, PERSO_POL_STA_REL
WHERE TEAM_ROL_REL.ROL_CD IN ('1','2')
AND TEAM_ROL_REL.T_ROL_REL_ID = TEAM_ROL_POL_REL.P_ROL_REL_ID
AND TEAM_ROL_POL_REL.P_POL_ID = PERSO_POL_STA_REL.P_POL_ID
AND PERSO_POL_STA_REL.STA_CD = 'A'
) PACTS
ON ABC.PKEY_SRC_OBJECT = PACTS.TEAM_ID;
For the two first flags (ISMASTER and ISAGENT) I get the result in less than 1min, but for the last flag (NUMPACTS) it runs few minutes without provide any result.
I think my statement is too heavy, maybe I should do it in a totally different way.
I think you have perhaps over complicated things.
You could do this (assuming I have understood your requirements correctly) like so:
WITH ttr AS (SELECT rltd_team_id,
COUNT(*) is_master
FROM team_team_rel
AND CODE = 'Double'
GROUP BY rltd_team_id),
trr AS (SELECT team_id,
COUNT(*) is_agent
FROM team_rol_rel
GROUP BY team_id)
pacts AS (SELECT trr1.team_id,
COUNT(*) num_pacts
FROM team_rol_rel trr1
INNER JOIN team_rol_pol_rel trpr ON (trr1.t_rol_rel_id = trpr.p_rol_rel_id)
INNER JOIN perso_pol_sta_rel ppsr ON (trpr.p_pol_id = ppsr.p_pol_id
WHERE trr1.rol_cd IN ('1', '2')
AND ppsr.st_cd = 'A'
GROUP BY trr1.team_id)
SELECT t.id pkey_src_object,
t.modf_dat update_date,
t.modf_usr updated_by,
p.first_nam first_name,
ttr.is_master,
trr.is_agent,
pacts.num_pacts
FROM team t
LEFT OUTER JOIN perso p ON t.id = p.team_id
LEFT OUTER JOIN ttr ON t.party_pty_id = ttr.rltd_team_id
LEFT OUTER JOIN trr ON t.party_pty_id = trr.team_id
LEFT OUTER JOIN pacts ON t.pkey_src_object = pacts.team_id;
N.B. untested, since you didn't provide any test data.

How can I optimize the SQL query?

I have a query an SQL query as follows, can anybody suggest any optimization for this; I think most of the effort is being done for the Union operation - is there anything else can be done to get the same result ?
Basically I wanna query first portion of the UNION and if for each record there is no result then the second portion need to be run. Please help.
:
SET dateformat dmy;
WITH incidentcategory
AS (
SELECT 1 ord, i.IncidentId, rl.Description Category FROM incident i
JOIN IncidentLikelihood l ON i.IncidentId = l.IncidentId
JOIN IncidentSeverity s ON i.IncidentId = s.IncidentId
JOIN LikelihoodSeverity ls ON l.LikelihoodId = ls.LikelihoodId AND s.SeverityId = ls.SeverityId
JOIN RiskLevel rl ON ls.RiskLevelId = rl.riskLevelId
UNION
SELECT 2 ord, i.incidentid,
rl.description Category
FROM incident i
JOIN incidentreportlikelihood l
ON i.incidentid = l.incidentid
JOIN incidentreportseverity s
ON i.incidentid = s.incidentid
JOIN likelihoodseverity ls
ON l.likelihoodid = ls.likelihoodid
AND s.severityid = ls.severityid
JOIN risklevel rl
ON ls.risklevelid = rl.risklevelid
) ,
ic AS (
SELECT ROW_NUMBER() OVER (PARTITION BY i.IncidentId ORDER BY (CASE WHEN incidentTime IS NULL THEN GETDATE() ELSE incidentTime END) DESC,ord ASC) rn,
i.incidentid,
dbo.Incidentdescription(i.incidentid, '',
'',
'', '')
IncidentDescription,
dbo.Dateconverttimezonecompanyid(closedtime,
i.companyid)
ClosedTime,
incidenttime,
incidentno,
Isnull(c.category, '')
Category,
opencorrectiveactions,
reportcompleted,
Isnull(classificationcompleted, 0)
ClassificationCompleted,
Cast (( CASE
WHEN closedtime IS NULL THEN 0
ELSE 1
END ) AS BIT)
IncidentClosed,
Cast (( CASE
WHEN investigatorfinishedtime IS NULL THEN 0
ELSE 1
END ) AS BIT)
InvestigationFinished,
Cast (( CASE
WHEN investigationcompletetime IS NULL THEN 0
ELSE 1
END ) AS BIT)
InvestigationComplete,
Cast (( CASE
WHEN investigatorassignedtime IS NULL THEN 0
ELSE 1
END ) AS BIT)
InvestigatorAssigned,
Cast (( CASE
WHEN (SELECT Count(*)
FROM incidentinvestigator
WHERE incidentid = i.incidentid
AND personid = 1588
AND tablename = 'AdminLevels') = 0
THEN 0
ELSE 1
END ) AS BIT)
IncidentInvestigator,
(SELECT dbo.Strconcat(osname)
FROM (SELECT TOP 10 osname
FROM incidentlocation l
JOIN organisationstructure o
ON l.locationid = o.osid
WHERE incidentid = i.incidentid
ORDER BY l.locorder) loc)
Location,
Isnull((SELECT TOP 1 teamleader
FROM incidentinvestigator
WHERE personid = 1588
AND tablename = 'AdminLevels'
AND incidentid = i.incidentid), 0)
TeamLeader,
incidentstatus,
incidentstatussearch
FROM incident i
LEFT OUTER JOIN incidentcategory c
ON i.incidentid = c.incidentid
WHERE i.isdeleted = 0
AND i.companyid = 158
AND incidentno <> 0
--AND reportcompleted = 1
--AND investigatorassignedtime IS NOT NULL
--AND investigatorfinishedtime IS NULL
--AND closedtime IS NULL
),
ic2 AS (
SELECT * FROM ic WHERE rn=1
)
SELECT * FROM ic2
--WHERE rownumber >= 0
-- AND rownumber < 0 + 10
--WHERE ic2.incidentid in(53327,53538)
--WHERE ic2.incidentid = 53338
ORDER BY incidentid DESC
Following is the execution plan I got:
https://www.dropbox.com/s/50dcpelr1ag4blp/Execution_Plan.sqlplan?dl=0
There are several issues:
1) use UNION ALL instead of UNION ALL to avoid the additional operation to aggregate the data.
2) try to modify the numerous function calls (e.g. dbo.Incidentdescription() ) to be an in-lie table valued function so you can reference it using CROSS APPLY or OUTER APPLY. Especially, if those functions referencing a table again.
3) move the subqueries from the SELECT part of the query to the FROM part using CROSS APPLY or OUTER APPLY again.
4) after the above is done, check the execution plan again for any missing indexes. Also, run the query with STATISTICS TIME, IO on to verify that the number of times a table
is referenced is correct (sometimes the execution plan put you in the wrong direction, especially if function calls are involved)...
Since the first inner query produces rows with ord=1 and the second produces rows with ord=2, you should use UNION ALL instead of UNION. UNION will filter out equal rows and since you will never get equal rows it is more efficient to use UNION ALL.
Also, rewrite your query to not use the WITH construct. I've had very bad experiences with this. Just use regular derived tables instead. In the case the query is still abnormally slow, try to serialize some derived tables to a temporary table and query the temporary table instead.
Try alternate approach by removing
(SELECT dbo.Strconcat(osname)
FROM (SELECT TOP 10 osname
FROM incidentlocation l
JOIN organisationstructure o
ON l.locationid = o.osid
WHERE incidentid = i.incidentid
ORDER BY l.locorder) loc)
Location,
Isnull((SELECT TOP 1 teamleader
FROM incidentinvestigator
WHERE personid = 1588
AND tablename = 'AdminLevels'
AND incidentid = i.incidentid), 0)
TeamLeader
from the SELECT. Avoid using complex functions/sub-queries in select.