SQL If statements - sql

IIf(#LASTCYCLEGASINJ.[rb gas]<=0,"", #LASTCYCLEWTRINJ.[RB WTR]/#LASTCYCLEGASINJ.RBGAS AS [WTR INJ/GAS INJ],
I have all my code working expect for the If statement. I know it needs a condition but I have tried many different things. Any help appreciated. Here is the entire code but everything seems to work but the If statements.
SELECT #ACTORSIINJ.UCI, #ACTORSIINJ.NAME,
#LASTCYCLEDAYS.CountOfDate AS DAYSLASTCYCLE,
#LASTCYCLEWTRINJ.DAYSWTR, #LASTCYCLEGASINJ.[DAYS GAS],
#LASTCYCLEGASINJ.AvgOfIGASVOL, #LASTCYCLEGASINJ.[RB GAS],
#LASTCYCLEWTRINJ.AvgOfIWTRVOL, #LASTCYCLEWTRINJ.RBWTR,
IIf(#LASTCYCLEGASINJ.[RB GAS]*#LASTCYCLEGASINJ.[DAYS GAS]<=0,(#LASTCYCLEWTRINJ.[RB WTR]*#LASTCYCLEWTRINJ.[DAYS WTR])/(#LASTCYCLEGASINJ.[RB GAS]*#LASTCYCLEGASINJ.[DAYS GAS]) AS WAGRATIO,
IIf(#LASTCYCLEGASINJ.[rb gas]<=0,"", #LASTCYCLEWTRINJ.[RB WTR]/#LASTCYCLEGASINJ.RBGAS AS [WTR INJ/GAS INJ],
#LAST90DAYWTRINJ.AvgOfIWTRVOL AS [Last 90 day wtr], #ACTORSIINJ.CoType, #ACTORSIINJ.CoPrdStatus, #InstUtilizationsStep3.[SumOfALLOCATED OIL],
#InstUtilizationsStep3.[SumOfALLOCATED GAS INJ], #InstUtilizationsStep3.Utilizations, #ACTORSIINJ.PatternName
into #LastCycleWagMetrics
FROM #InstUtilizationsStep3
RIGHT JOIN
(
(
(
(
(#ACTORSIINJ LEFT JOIN #LAST90DAYGASINJ ON #ACTORSIINJ.UCI = #LAST90DAYGASINJ.UCI)
LEFT JOIN #LAST90DAYWTRINJ ON #ACTORSIINJ.UCI = #LAST90DAYWTRINJ.UCI)
LEFT JOIN #LASTCYCLEDAYS ON #ACTORSIINJ.UCI = #LASTCYCLEDAYS.UCI)
LEFT JOIN #LASTCYCLEWTRINJ ON #ACTORSIINJ.UCI = #LASTCYCLEWTRINJ.UCI)
LEFT JOIN #LASTCYCLEGASINJ ON #ACTORSIINJ.UCI = #LASTCYCLEGASINJ.UCI
) ON #InstUtilizationsStep3.PatternName = #ACTORSIINJ.PatternName

In addition to the missing parentheses that others have mentioned, I believe you are going to run into an error with have a string type in the second parameter and a number in the third parameter of the iif. I would change the "" to null or 0

It looks like the IIF() functions are missing their right closing parentheses ()).
Both the short example at the top and the place where it's repeated in the larger block from the question follow this form:
IIf( A, B, C As ColumnName
When it should look like this:
IIf(A, B, C) As ColumnName
Next, here is the better way to write those JOINs. Note how it also rearranged the order so the RIGHT JOIN could be a LEFT JOIN instead. Every RIGHT JOIN can always be rewritten as a LEFT JOIN, and it is almost always beneficial to do so. Logicially both versions will have the same result, but this will be MUCH easier to reason about and maintain.
FROM #ACTORSIINJ a
LEFT JOIN #LAST90DAYGASINJ l90g ON a.UCI = l90g.UCI
LEFT JOIN #LAST90DAYWTRINJ l90w ON a.UCI = l90w.UCI
LEFT JOIN #LASTCYCLEDAYS cd ON a.UCI = cd.UCI
LEFT JOIN #LASTCYCLEWTRINJ cw ON a.UCI = cw.UCI
LEFT JOIN #LASTCYCLEGASINJ cg ON a.UCI = cg.UCI
LEFT JOIN #InstUtilizationsStep3 s3 ON s3.PatternName = a.PatternName
Now try this:
SELECT a.UCI, a.NAME, cd.CountOfDate AS DAYSLASTCYCLE,
cw.DAYSWTR, cg.[DAYS GAS], cg.AvgOfIGASVOL, cg.[RB GAS],
cw.AvgOfIWTRVOL, cw.RBWTR,
IIf(cg.[RB GAS]*cg.[DAYS GAS]<=0,
NULL,
(cw.[RB WTR]*cw.[DAYS WTR])/(cg.[RB GAS]*cg.[DAYS GAS]) ) AS WAGRATIO,
IIf(cg.[rb gas]<=0,
NULL,
cw.[RB WTR]/cg.RBGAS) AS [WTR INJ/GAS INJ],
l90.AvgOfIWTRVOL AS [Last 90 day wtr], a.CoType, a.CoPrdStatus,
s3.[SumOfALLOCATED OIL], s3.[SumOfALLOCATED GAS INJ], s3.Utilizations,
a.PatternName
into #LastCycleWagMetrics
FROM #ACTORSIINJ a
LEFT JOIN #LAST90DAYGASINJ l90g ON a.UCI = l90g.UCI
LEFT JOIN #LAST90DAYWTRINJ l90w ON a.UCI = l90w.UCI
LEFT JOIN #LASTCYCLEDAYS cd ON a.UCI = cd.UCI
LEFT JOIN #LASTCYCLEWTRINJ cw ON a.UCI = cw.UCI
LEFT JOIN #LASTCYCLEGASINJ cg ON a.UCI = cg.UCI
LEFT JOIN #InstUtilizationsStep3 s3 ON s3.PatternName = a.PatternName
Or this:
SELECT a.UCI, a.NAME, cd.CountOfDate AS DAYSLASTCYCLE,
cw.DAYSWTR, cg.[DAYS GAS], cg.AvgOfIGASVOL,cg.[RB GAS],
cw.AvgOfIWTRVOL, cw.RBWTR,
CASE WHEN cg.[RB GAS]*cg.[DAYS GAS] > 0
THEN (cw.[RB WTR] * cw.[DAYS WTR])/(cg.[RB GAS] * cg.[DAYS GAS])
END AS WAGRATIO,
CASE WHEN cg.[rb gas]>0,
THEN cw.[RB WTR]/cg.RBGAS
END AS [WTR INJ/GAS INJ],
l90w.AvgOfIWTRVOL AS [Last 90 day wtr], a.CoType, a.CoPrdStatus,
s3.[SumOfALLOCATED OIL], s3.[SumOfALLOCATED GAS INJ], s3.Utilizations,
a.PatternName
into #LastCycleWagMetrics
FROM #ACTORSIINJ a
LEFT JOIN #LAST90DAYGASINJ l90g ON a.UCI = l90g.UCI
LEFT JOIN #LAST90DAYWTRINJ l90w ON a.UCI = l90w.UCI
LEFT JOIN #LASTCYCLEDAYS cd ON a.UCI = cd.UCI
LEFT JOIN #LASTCYCLEWTRINJ cw ON a.UCI = cw.UCI
LEFT JOIN #LASTCYCLEGASINJ cg ON a.UCI = cg.UCI
LEFT JOIN #InstUtilizationsStep3 s3 ON s3.PatternName = a.PatternName
Note this last version inverted the conditional operators. It also used CASE expressions instead of IIF(), which is the ansi standard way (IIf() is not part of the SQL standard).
Adding alias mnemonics also let us put everything into a reasonably-sized code window with no scrolling anywhere. It should be standard practice to use aliases in any query referencing at least three different tables or views.
Finally, that looks like a LOT of temp tables, which seems... well... calling it "sub-optimal" is putting it mildly. I'd expect most of the code to build up those temp tables could be re-written using Common Table Expressions, which could potentially improve performance here by multiple orders of magnitude.

I got it. The divide by zero error seemed to be hanging it up.
SELECT #InstUtilizationsStep1.PatternName, Sum(#InstUtilizationsStep1.[ALLOCATED OIL]) AS [SumOfALLOCATED OIL],
Sum(#InstUtilizationsStep1.[ALLOCATED GAS INJ]) AS [SumOfALLOCATED GAS INJ],
IIf(Sum([allocated oil])=0,Null,Sum(#InstUtilizationsStep1.[allocated gas inj])/Sum([allocated oil])) AS Utilizations
into #InstUtilizationsStep3
FROM #InstUtilizationsStep1
INNER JOIN #InstUtilizationsStep2 ON (#InstUtilizationsStep1.PatternName = #InstUtilizationsStep2.PatternName)
AND (#InstUtilizationsStep1.Date = #InstUtilizationsStep2.Date)
GROUP BY #InstUtilizationsStep1.PatternName

Related

LEFT JOIN expression not supported

I need to do a query with a left outer join just like below, however Access is showing a warning dialog "JOIN expression not supported".I understand that Access doesn't support INNER JOIN nested inside a LEFT JOIN but as I am a beginner in SQL I don't see any other way to get the same result.
The goal of the query is to get everything that is in the select even when InvoiceItems.Amount is null.
SELECT MainOrder.OrderNumber, OrderComponent.ArticleNumber, SupplierOrderMain.*, InvoiceItems.Amount
FROM InvoiceItems LEFT JOIN
((MainOrder INNER JOIN
OrderComponent
ON MainOrder.OrderNumber = OrderComponent.OrderNumber
) INNER JOIN
SupplierOrderMain
ON OrderComponent.ID = SupplierOrderMain.OrderComponentID
)
ON InvoiceItems.OrderComponent = OrderComponent.ID;
I'm not sure why you would want outer joins in this situation at all (you don't explain why). But just start with the table where you want to keep everything and work from there:
SELECT MainOrder.OrderNumber, OrderComponent.ArticleNumber, SupplierOrderMain.*, InvoiceItems.Amount
FROM ((InvoiceItems LEFT JOIN
OrderComponent
ON InvoiceItems.OrderComponent = OrderComponent.ID
) LEFT JOIN
MainOrder
ON MainOrder.OrderNumber = OrderComponent.OrderNumber
) LEFT JOIN
SupplierOrderMain
ON OrderComponent.ID = SupplierOrderMain.OrderComponentID

Postgresql - Conditional Join if data exist

My current query show the data from the table called "Buque" and has some references from another tables. The problem is when i execute the query it never shows the result because it consumes too much memory i guess.
The current query i have
select buq.buq_codigo, tbu.tbu_codigo, tbu.tbu_nombre, pai.pai_codigo, pai.pai_nombre,
pue.pto_codigo, pue.pto_nombre, lin.lin_codigo, lin.lin_nombre, tra.tra_codigo,
tra.tra_nombre, buq.buq_nombre, buq.buq_des, buq.num_trb, buq.num_eslora,
buq.max_tons, buq.reg_lloyd, buq.buq_codigo1, buq.codigo_omi,
case buq.buq_estado when 'A' then 'Activo' else 'Inactivo' end as buq_estado
from publico.mae_buque as buq, publico.mae_tipbuque as tbu, publico.mae_pais as pai,
publico.mae_puerto as pue, publico.mae_linea as lin, publico.mae_trafico as tra
where buq.tbu_codigo = tbu.tbu_codigo or
buq.pai_codigo = pai.pai_codigo or
buq.pto_codigo = pue.pto_codigo or
buq.lin_codigo = lin.lin_codigo or
buq.tra_codigo = tra.tra_codigo
I also tried with inner joins but the problem is it returns me the data that meets the conditions of the joins. In other words, if the join has data to compare, returns the name, if not, show the null data.
The query must return me 611 records, with inner joins returns 68 records.
Concerning your desired result, use left outer joins, which fill up any non-existing rows of the right hand side table with null-values;
Concerning the out of memory issue, note that you used or to connect your tables; this actually leads to the fact that almost every record of the involved tables is connected to almost every other record (almost a cross join / cartesian product); This can get very large if you connect 6 tables...
select buq.buq_codigo, tbu.tbu_codigo, tbu.tbu_nombre, pai.pai_codigo, pai.pai_nombre,
pue.pto_codigo, pue.pto_nombre, lin.lin_codigo, lin.lin_nombre, tra.tra_codigo,
tra.tra_nombre, buq.buq_nombre, buq.buq_des, buq.num_trb, buq.num_eslora,
buq.max_tons, buq.reg_lloyd, buq.buq_codigo1, buq.codigo_omi,
case buq.buq_estado when 'A' then 'Activo' else 'Inactivo' end as buq_estado
from publico.mae_buque as buq
left outer join publico.mae_tipbuque as tbu on buq.tbu_codigo = tbu.tbu_codigo
left outer join publico.mae_pais as pai on (buq.pai_codigo = pai.pai_codigo)
left outer join publico.mae_puerto as pue on (buq.pto_codigo = pue.pto_codigo)
left outer join publico.mae_linea as lin on (buq.lin_codigo = lin.lin_codigo)
left outer join publico.mae_trafico as tra on (buq.tra_codigo = tra.tra_codigo)
You have to use left outer join:
select *
from
publico.mae_buque as buq
left outer join publico.mae_tipbuque as tbu on (buq.tbu_codigo = tbu.tbu_codigo)
left outer join publico.mae_pais as pai on (buq.pai_codigo = pai.pai_codigo)
left outer join publico.mae_puerto as pue on (buq.pto_codigo = pue.pto_codigo )
left outer join publico.mae_linea as lin on (buq.lin_codigo = lin.lin_codigo)
left outer join publico.mae_trafico as tra on (buq.tra_codigo = tra.tra_codigo);

LEFT JOIN ON COALESCE(a, b, c) - very strange behavior

I have encountered very strange behavior of my query and I wasted a lot of time to understand what causes it, in vane. So I am asking for your help.
SELECT count(*) FROM main_table
LEFT JOIN front_table ON front_table.pk = main_table.fk_front_table
LEFT JOIN info_table ON info_table.pk = front_table.fk_info_table
LEFT JOIN key_table ON key_table.pk = COALESCE(info_table.fk_key_table, front_table.fk_key_table_1, front_table.fk_key_table_2)
LEFT JOIN side_table ON side_table.fk_front_table = front_table.pk
WHERE side_table.pk = (SELECT MAX(pk) FROM side_table WHERE fk_front_table = front_table.pk)
OR side_table.pk IS NULL
Seems like a simple join query, with coalesce, I've used this technique before(not too many times) and it worked right.
In this query I don't ever get nulls for side_table.pk. If I remove coalesce or just don't use key_table, then the query returns rows with many null side_table.pk, but if I add coalesce join, I can't get those nulls.
It seems key_table and side_table don't have anything in common, but the result is so weird.
Also, when I don't use side_table and WHERE clause, the count(*) result with coalesce and without differs, but I can't see any pattern in rows missing, it seems random!
Real query:
SELECT ECHANGE.EXC_AUTO_KEY, STOCK_RESERVATIONS.STR_AUTO_KEY FROM EXCHANGE
LEFT JOIN WO_BOM ON WO_BOM.WOB_AUTO_KEY = EXCHANGE.WOB_AUTO_KEY
LEFT JOIN VIEW_WO_SUB ON VIEW_WO_SUB.WOO_AUTO_KEY = WO_BOM.WOO_AUTO_KEY
LEFT JOIN STOCK stock3 ON stock3.STM_AUTO_KEY = EXCHANGE.STM_AUTO_KEY
LEFT JOIN STOCK stock2 ON stock2.STM_AUTO_KEY = EXCHANGE.ORIG_STM
LEFT JOIN CONSIGNMENT_CODES con2 ON con2.CNC_AUTO_KEY = stock2.CNC_AUTO_KEY
LEFT JOIN CONSIGNMENT_CODES con3 ON con3.CNC_AUTO_KEY = stock3.CNC_AUTO_KEY
LEFT JOIN CI_UTL ON CI_UTL.CUT_AUTO_KEY = EXCHANGE.CUT_AUTO_KEY
LEFT JOIN PART_CONDITION_CODES pcc2 ON pcc2.PCC_AUTO_KEY = stock2.PCC_AUTO_KEY
LEFT JOIN PART_CONDITION_CODES pcc3 ON pcc3.PCC_AUTO_KEY = stock3.PCC_AUTO_KEY
LEFT JOIN STOCK_RESERVATIONS ON STOCK_RESERVATIONS.STM_AUTO_KEY = stock3.STM_AUTO_KEY
LEFT JOIN WAREHOUSE wh2 ON wh2.WHS_AUTO_KEY = stock2.WHS_ORIGINAL
LEFT JOIN SM_HISTORY ON (SM_HISTORY.STM_AUTO_KEY = EXCHANGE.ORIG_STM AND SM_HISTORY.WOB_REF = EXCHANGE.WOB_AUTO_KEY)
LEFT JOIN RC_DETAIL ON stock3.RCD_AUTO_KEY = RC_DETAIL.RCD_AUTO_KEY
LEFT JOIN RC_HEADER ON RC_HEADER.RCH_AUTO_KEY = RC_DETAIL.RCH_AUTO_KEY
LEFT JOIN WAREHOUSE wh3 ON wh3.WHS_AUTO_KEY = COALESCE(RC_DETAIL.WHS_AUTO_KEY, stock3.WHS_ORIGINAL, stock3.WHS_AUTO_KEY)
WHERE STOCK_RESERVATIONS.STR_AUTO_KEY = (SELECT MAX(STR_AUTO_KEY) FROM STOCK_RESERVATIONS WHERE STM_AUTO_KEY = stock3.STM_AUTO_KEY)
OR STOCK_RESERVATIONS.STR_AUTO_KEY IS NULL
Removing LEFT JOIN WAREHOUSE wh3 gives me about unique EXC_AUTO_KEY values with a lot of NULL STR_AUTO_KEY, while leaving this row removes all NULL STR_AUTO_KEY.
I recreated simple tables with numbers with the same structure and query works without any problems o.0
I have a feeling COALESCE is acting as a REQUIRED flag for the joined table, hence shooting the LEFT JOIN to become an INNER JOIN.
Try this:
SELECT COUNT(*)
FROM main_table
LEFT JOIN front_table ON front_table.pk = main_table.fk_front_table
LEFT JOIN info_table ON info_table.pk = front_table.fk_info_table
LEFT JOIN key_table ON key_table.pk = NVL(info_table.fk_key_table, NVL(front_table.fk_key_table_1, front_table.fk_key_table_2))
LEFT JOIN (SELECT fk_, MAX(pk) as pk FROM side_table GROUP BY fk_) st ON st.fk_ = front_table.pk
NVL might behave just the same though...
I undertood what was the problem (not entirely though): there is a LEFT JOIN VIEW_WO_SUB in original query, 3rd line. It causes this query to act in a weird way.
When I replaced the view with the other table which contained the information I needed, the query started returning right results.
Basically, with this view join, NVL, COALESCE or CASE join with combination of certain arguments did not work along with OR clause in WHERE subquery, all rest was fine. ALthough, I could get the query to work with this view join, by changing the order of joined tables, I had to place table participating in where subquery to the bottom.

Is there a better way to write this Oracle SQL query?

I have been using Oracle SQL for around 6 months so still a beginner. I need to query the database to get information on all items on a particular order (order number is via $_GET['id']).
I have come up with the below query, it works as expected and as I need but I do not know whether I am over complicating things which would slow the query down at all. I understand there are a number of ways to do a single thing and there may be better methods to write this query since I am a beginner.
I am using Oracle 8i (due to this is the version an application we use is supplied with) so I believe that some JOIN etc. are not available in this version, but is there a better way to write a query such as the below?
SELECT auf_pos.auf_pos,
(SELECT auf_stat.anz
FROM auf_stat
WHERE auf_stat.auf_pos = auf_pos.auf_pos
AND auf_stat.auf_nr = ".$_GET['id']."),
(SELECT auf_text.zl_str
FROM auf_text
WHERE auf_text.zl_mod = 0
AND auf_text.auf_pos = auf_pos.auf_pos
AND auf_text.auf_nr = ".$_GET['id']."),
(SELECT glas_daten_basis.gl_bez
FROM glas_daten_basis
WHERE glas_daten_basis.idnr = auf_pos.glas1),
(SELECT lzr_daten.lzr_breite
FROM lzr_daten
WHERE lzr_daten.lzr_idnr = auf_pos.lzr1),
(SELECT glas_daten_basis.gl_bez
FROM glas_daten_basis
WHERE glas_daten_basis.idnr = auf_pos.glas2),
auf_pos.breite,
auf_pos.hoehe,
auf_pos.spr_jn
FROM auf_pos
WHERE auf_pos.auf_nr = ".$_GET['id']."
Thanks in advance to any Oracle gurus that could help this beginner out!
You could rewrite it using joins. If your subselects aren't expected to return any NULL values, then you can use INNER JOINS:
SELECT auf_pos.auf_pos,
auf_stat.anz,
auf_text.zl_str,
glas_daten_basis.gl_bez,
lzr_daten.lzr_breite,
glas_daten_basis.gl_bez,
auf_pos.breite,
auf_pos.hoehe,
auf_pos.spr_jn
FROM auf_pos
INNER JOIN auf_stat ON auf_stat.auf_pos = auf_pos.auf_pos AND auf_stat.auf_nr = ".$_GET['id'].")
INNER JOIN auf_text ON auf_text.zl_mod = 0 AND auf_text.auf_pos = auf_pos.auf_pos AND auf_text.auf_nr = ".$_GET['id'].")
INNER JOIN glas_daten_basis ON glas_daten_basis.idnr = auf_pos.glas1
INNER JOIN lzr_daten ON lzr_daten.lzr_idnr = auf_pos.lzr1
INNER JOIN glas_daten_basis ON glas_daten_basis.idnr = auf_pos.glas2
Or if there are cases where you wouldn't have matches on all the tables, you could replace the INNER joins with LEFT OUTER joins:
SELECT auf_pos.auf_pos,
auf_stat.anz,
auf_text.zl_str,
glas_daten_basis.gl_bez,
lzr_daten.lzr_breite,
glas_daten_basis.gl_bez,
auf_pos.breite,
auf_pos.hoehe,
auf_pos.spr_jn
FROM auf_pos
LEFT OUTER JOIN auf_stat ON auf_stat.auf_pos = auf_pos.auf_pos AND auf_stat.auf_nr = ".$_GET['id'].")
LEFT OUTER JOIN auf_text ON auf_text.zl_mod = 0 AND auf_text.auf_pos = auf_pos.auf_pos AND auf_text.auf_nr = ".$_GET['id'].")
LEFT OUTER JOIN glas_daten_basis ON glas_daten_basis.idnr = auf_pos.glas1
LEFT OUTER JOIN lzr_daten ON lzr_daten.lzr_idnr = auf_pos.lzr1
LEFT OUTER JOIN glas_daten_basis ON glas_daten_basis.idnr = auf_pos.glas2
Whether or not you see any performance gains is debatable. As I understand it, the Oracle query optimizer should take your query and execute it with a similar plan to the join queries, but this is dependent on a number of factors, so the best thing to do it give it a try..

How to improve the performance of a SQL query even after adding indexes?

I am trying to execute the following sql query but it takes 22 seconds to execute. the number of returned items is 554192. I need to make this faster and have already put indexes in all the tables involved.
SELECT mc.name AS MediaName,
lcc.name AS Country,
i.overridedate AS Date,
oi.rating,
bl1.firstname + ' ' + bl1.surname AS Byline,
b.id BatchNo,
i.numinbatch ItemNumberInBatch,
bah.changedatutc AS BatchDate,
pri.code AS IssueNo,
pri.name AS Issue,
lm.neptunemessageid AS MessageNo,
lmt.name AS MessageType,
bl2.firstname + ' ' + bl2.surname AS SourceFullName,
lst.name AS SourceTypeDesc
FROM profiles P
INNER JOIN profileresults PR
ON P.id = PR.profileid
INNER JOIN items i
ON PR.itemid = I.id
INNER JOIN batches b
ON b.id = i.batchid
INNER JOIN itemorganisations oi
ON i.id = oi.itemid
INNER JOIN lookup_mediachannels mc
ON i.mediachannelid = mc.id
LEFT OUTER JOIN lookup_cities lc
ON lc.id = mc.cityid
LEFT OUTER JOIN lookup_countries lcc
ON lcc.id = mc.countryid
LEFT OUTER JOIN itembylines ib
ON ib.itemid = i.id
LEFT OUTER JOIN bylines bl1
ON bl1.id = ib.bylineid
LEFT OUTER JOIN batchactionhistory bah
ON b.id = bah.batchid
INNER JOIN itemorganisationissues ioi
ON ioi.itemorganisationid = oi.id
INNER JOIN projectissues pri
ON pri.id = ioi.issueid
LEFT OUTER JOIN itemorganisationmessages iom
ON iom.itemorganisationid = oi.id
LEFT OUTER JOIN lookup_messages lm
ON iom.messageid = lm.id
LEFT OUTER JOIN lookup_messagetypes lmt
ON lmt.id = lm.messagetypeid
LEFT OUTER JOIN itemorganisationsources ios
ON ios.itemorganisationid = oi.id
LEFT OUTER JOIN bylines bl2
ON bl2.id = ios.bylineid
LEFT OUTER JOIN lookup_sourcetypes lst
ON lst.id = ios.sourcetypeid
WHERE p.id = #profileID
AND b.statusid IN ( 6, 7 )
AND bah.batchactionid = 6
AND i.statusid = 2
AND i.isrelevant = 1
when looking at the execution plan I can see an step which is costing 42%. Is there any way I could get this to a lower threshold or any way that I can improve the performance of the whole query.
Remove the profiles table as it is not needed and change the WHERE clause to
WHERE PR.profileid = #profileID
You have a left outer join on the batchactionhistory table but also have a condition in your WHERE clause which turns it back into an inner join. Change you code to this:
LEFT OUTER JOIN batchactionhistory bah
ON b.id = bah.batchid
AND bah.batchactionid = 6
You don't need the batches table as it is used to join other tables which could be joined directly and to show the id in you SELECT which is also available in other tables. Make the following changes:
i.batchidid AS BatchNo,
LEFT OUTER JOIN batchactionhistory bah
ON i.batchidid = bah.batchid
Are any of the fields that are used in joins or the WHERE clause from tables that contain large amounts of data but are not indexed. If so try adding an index on at time to the largest table.
Do you need every field in the result - if you could loose one or to you maybe could reduce the number of tables further.
First, if this is not a stored procedure, make it one. That's a lot of text for sql server to complile.
Next, my experience is that "worst practices" are occasionally a good idea. Specifically, I have been able to improve performance by splitting large queries into a couple or three small ones and assembling the results.
If this query is associated with a .net, coldfusion, java, etc application, you might be able to do the split/re-assemble in your application code. If not, a temporary table might come in handy.