Performance : Left JOIN with IS NULL join condition in SQLite - database

select *
from Dummy LEFT JOIN data_stream_2
ON ((Dummy.id_2=data_stream_2.id_2) OR
(Dummy.id_2 IS NULL and data_stream_2.id_2 IS NULL))
This query takes 26 seconds. The moment I remove the IS NULL check, i.e
select *
from Dummy LEFT JOIN data_stream_2
ON ((Dummy.id_2=data_stream_2.id_2))
it takes only 1.3 seconds.
How can I make the query faster?
It us similar to this case Slow query with left outer join and is null condition but the difference is in his case join was not really required since he was using only columns from Dummy and not from data_stream_2. I need columns from both.

In the general case, you can separate the two parts of the OR into two parts of a compound query:
SELECT *
FROM Dummy
LEFT JOIN data_stream_2
ON Dummy.id_2 = data_stream_2.id_2
UNION ALL
SELECT *
FROM Dummy
JOIN data_stream_2
ON Dummy.id_2 IS NULL AND data_stream_2.id_2 IS NULL;
However, SQLite's IS operator can use arbitrary expressions on either side, and supports index optimizations, so you can simply use it to compare the IDs:
SELECT *
FROM Dummy
LEFT JOIN data_stream_2
ON Dummy.id_2 IS data_stream_2.id_2;

Related

RIGHT\LEFT Join does not provide null values without condition

I have two tables one is the lookup table and the other is the data table. The lookup table has columns named cycleid, cycle. The data table has SID, cycleid, cycle. Below is the structure of the tables.
If you check the data table, the SID may have all the cycles and may not have all the cycles. I want to output the SID completed as well as missed cycles.
I right joined the lookup table and retrieved the missing as well as completed cycles. Below is the query I used.
SELECT TOP 1000 [SID]
,s4.[CYCLE]
,s4.[CYCLEID]
FROM [dbo].[data] s3 RIGHT JOIN
[dbo].[lookup_data] s4 ON s3.CYCLEID = s4.CYCLEID
The query is not displaying me the missed values when I query for all the SID's. When I specifically query for a SID with the below query i am getting the correct result including the missed ones.
SELECT TOP 1000 [SID]
,s4.[CYCLE]
,s4.[CYCLEID]
FROM [dbo].[data] s3 RIGHT JOIN [dbo].[lookup_data] s4
ON s3.CYCLEID = s4.CYCLEID
AND s3.SID = 101002
ORDER BY [SID], s4.[CYCLEID]
As I am supplying this query into tableau I cannot provide the sid value in the query. I want to return all the sid's and from tableau I will be do the rest of the things.
The expected output that i need is as shown below.
I wrote a cross join query like below to acheive my expected output
SELECT DISTINCT
tab.CYCLEID
,tab.SID
,d.CYCLE
FROM ( SELECT d.SID
,d.[CYCLE]
,e.CYCLEID
FROM ( SELECT e.sid
,e.CYCLE
FROM [db_temp].[dbo].[Sheet3$] e
) d
CROSS JOIN [db_temp].[dbo].[Sheet4$] e
) tab
LEFT OUTER JOIN [db_temp].[dbo].[Sheet3$] d
ON d.CYCLEID = tab.CYCLEID
AND d.SID = tab.SID
ORDER BY tab.SID
,tab.CYCLEID;
However I am not able to use this query for more scenarios as my data set have nearly 20 to 40 columns and i am having issues when i use the above one.
Is there any way to do this in a simpler manner with only left or right join itself? I want the query to return all the missing values and the completed values for the all the SID's instead of supplying a single sid in the query.
You can create a master table first (combine all SID and CYCLE ID), then right join with the data table
;with ctxMaster as (
select distinct d.SID, l.CYCLE, l.CYCLEID
from lookup_data l
cross join data d
)
select d.SID, m.CYCLE, m.CYCLEID
from ctxMaster m
left join data d on m.SID = d.SID and m.CYCLEID = d.CYCLEID
order by m.SID, m.CYCLEID
Fiddle
Or if you don't want to use common table expression, subquery version:
select d.SID, m.CYCLE, m.CYCLEID
from (select distinct d.SID, l.CYCLE, l.CYCLEID
from lookup_data l
cross join data d) m
left join data d on m.SID = d.SID and m.CYCLEID = d.CYCLEID
order by m.SID, m.CYCLEID

Referencing Results of Multiple Temporary Tables in SQL Server

I’m using SQL Server 2008
I have joins written something like the following, where the first join is encapsulated in a ‘With as’ statement so that I can name the output table as ‘A’ and then reference the ‘A’ resulting table in the next select and Join seen beneath it.
This works perfectly fine. What I would like to do then is reference that second table for another select statement and join, but when I try to wrap it in a ‘With as’ statement as well, the editor does not accept it as legitimate syntax for the second instance of 'With as'.
How can I subset resulting tables to reference in further select and join statements? I do not have permission to write to the database, so I can not create permanent tables in the database.
Thank you.
With A as
(
SELECT POL.[COMPANY_CODE]
,POL.[POLICY_NUMBER]
,POL.[STATUS_CODE]
,POL.ORIG_CLIENT_NUM
,TA.LINE
FROM [SamsReporting].[dbo].[POLICY] POL
Left join [SamsReporting].[dbo].[Transact] TA
ON TA.POLICY_NUMBER = POL.POLICY_NUMBER and TA.BASE_Account = 'B'
)
Select PM.POLICY_NUMBER
,A.[COMPANY_CODE]
,A.[POLICY_NUMBER]
,A.[Policy Status]
,eApp.SourceCode
From A
Left Join Web.dbo.Pmetrics PM on A.POLICY_NUMBER=PM.POLICY_NUMBER
Left Outer Join DDP.pol.eAppStaging eApp
on A.POLICY_NUMBER=eApp.PolicyNumber
where eApp.SourceCode = 'HAQ' or eApp.SourceCode = 'PLS'
Common Table Expressions (CTEs) can build upon each other as you would like. For example, you can do this:
WITH CTE1 AS (SELECT * FROM Table 1)
, CTE2 AS (SELECT * FROM CTE1)
, CTE3 AS (SELECT * FROM CTE2)
You only need the WITH statement for the first CTE. After that just use the CTE name, as in my example.
Hope that helps,
Ash
Sounds like a syntax issue to me. Google CTE (Common Table Expression) and review some examples of how they are formed.
With A as
(SELECT POL.[COMPANY_CODE]
,POL.[POLICY_NUMBER]
,POL.[STATUS_CODE]
,POL.ORIG_CLIENT_NUM
,TA.LINE
FROM [SamsReporting].[dbo].[POLICY] POL
Left join [SamsReporting].[dbo].[Transact] TA
ON TA.POLICY_NUMBER = POL.POLICY_NUMBER and TA.BASE_Account = 'B'),
B as (
Select PM.POLICY_NUMBER
,A.[COMPANY_CODE]
,A.[POLICY_NUMBER]
,A.[Policy Status]
,eApp.SourceCode
From A
Left Join Web.dbo.Pmetrics PM on A.POLICY_NUMBER=PM.POLICY_NUMBER
Left Outer Join DDP.pol.eAppStaging eApp
on A.POLICY_NUMBER=eApp.PolicyNumber
where eApp.SourceCode = 'HAQ' or eApp.SourceCode = 'PLS')
Select *
From B -- inner join some table
where some condition = 1

How to join one select with another when the first one not always returns a value for specific row?

I have a complex query to retrieve some results:
EDITED QUERY (added the UNION ALL):
SELECT t.*
FROM (
SELECT
dbo.Intervencao.INT_Processo, analista,
ETS.ETS_Sigla, ATC.ATC_Sigla, PAT.PAT_Sigla, dbo.Assunto.SNT_Peso,
CASE
WHEN ETS.ETS_Sigla = 'PE' AND (PAT.PAT_Sigla = 'LIB' OR PAT.PAT_Sigla = 'LBR') THEN (0.3*SNT_Peso)
WHEN ETS.ETS_Sigla = 'CD' THEN (0.3*SNT_Peso)*0.3
ELSE SNT_Peso
END AS PESOAREA,
CASE
WHEN a.max_TEA_FimTarefa IS NULL THEN a.max_TEA_InicioTarefa
ELSE a.max_TEA_FimTarefa
END AS DATA_INICIO_TERMINO,
ROW_NUMBER() OVER (PARTITION BY ATC.ATC_Sigla, a.SRV_Id ORDER BY TEA_FimTarefa DESC) AS seqnum
FROM dbo.Tarefa AS t
INNER JOIN (
SELECT
MAX(dbo.TarefaEtapaAreaTecnica.TEA_InicioTarefa) AS max_TEA_InicioTarefa,
MAX (dbo.TarefaEtapaAreaTecnica.TEA_FimTarefa) AS max_TEA_FimTarefa,
dbo.Pessoa.PFJ_Descri AS analista, dbo.AreaTecnica.ATC_Id, dbo.Tarefa.SRV_Id
FROM dbo.TarefaEtapaAreaTecnica
LEFT JOIN dbo.Tarefa ON dbo.TarefaEtapaAreaTecnica.TRF_Id = dbo.Tarefa.TRF_Id
LEFT JOIN dbo.AreaTecnica ON dbo.TarefaEtapaAreaTecnica.ATC_Id = dbo.AreaTecnica.ATC_Id
LEFT JOIN dbo.ServicoAreaTecnica ON dbo.TarefaEtapaAreaTecnica.ATC_Id = dbo.ServicoAreaTecnica.ATC_Id
AND dbo.Tarefa.SRV_Id = dbo.ServicoAreaTecnica.SRV_Id
INNER JOIN dbo.Pessoa ON dbo.Pessoa.PFJ_Id = dbo.ServicoAreaTecnica.PFJ_Id_Analista
GROUP BY dbo.AreaTecnica.ATC_Id, dbo.Tarefa.SRV_Id, dbo.Pessoa.PFJ_Descri
) AS a ON t.SRV_Id = a.SRV_Id
INNER JOIN dbo.TarefaEtapaAreaTecnica AS TarefaEtapaAreaTecnica_1 ON
t.TRF_Id = TarefaEtapaAreaTecnica_1.TRF_Id
AND a.ATC_Id = TarefaEtapaAreaTecnica_1.ATC_Id
AND a.max_TEA_InicioTarefa = TarefaEtapaAreaTecnica_1.TEA_InicioTarefa
LEFT JOIN AreaTecnica ATC ON TarefaEtapaAreaTecnica_1.ATC_Id = ATC.ATC_Id
LEFT JOIN Etapa ETS ON TarefaEtapaAreaTecnica_1.ETS_Id = ETS.ETS_Id
LEFT JOIN ParecerTipo PAT ON TarefaEtapaAreaTecnica_1.PAT_Id = PAT.PAT_Id
LEFT OUTER JOIN dbo.Servico ON a.SRV_Id = dbo.Servico.SRV_Id
INNER JOIN dbo.Intervencao ON dbo.Servico.INT_Id = dbo.Intervencao.INT_Id
LEFT JOIN dbo.Assunto ON dbo.Servico.SNT_Id = dbo.Assunto.SNT_Id
) t
The result is following:
It works good, the problem is that I was asked that if when a row is not present on this query, it must contain values from another table (ServicoAreaTecnica), so I got this query for the other table based on crucial information of the first query. So if I UNION ALL I get this:
Query1 +
UNION ALL
SELECT INN.INT_Processo,
PES.PFJ_Descri,
NULL, --ETS.ETS_Sigla,
ART.ATC_Sigla,
NULL ,--PAT.PAT_Sigla,
ASS.SNT_Peso,
NULL, --PESOAREA
NULL, --DATA_INICIO_TERMINO
NULL --seqnum
FROM dbo.ServicoAreaTecnica AS SAT
INNER JOIN dbo.AreaTecnica AS ART ON ART.ATC_Id = SAT.ATC_Id
INNER JOIN dbo.Servico AS SER ON SER.SRV_Id = SAT.SRV_Id
INNER JOIN dbo.Assunto AS ASS ON ASS.SNT_Id = SER.SNT_Id
INNER JOIN dbo.Intervencao AS INN ON INN.INT_Id = SER.INT_Id
INNER JOIN dbo.Pessoa AS PES ON PES.PFJ_Id = SAT.PFJ_Id_Analista
The result is following:
So what I want to do is to remove row number 1 because row number 2 exists on the first query, I think I got it explained better this time. The result should be only row number 1, row number 2 would appear only if query 1 doesn't retrieve a row for that particular INN.INT_Processo.
Thanks!
Ok, there are two ways to reduce your record set. Given that you've already written the code to produce the table with the extra rows, it might be easiest to just add code to reduce that:
Select * from
(Select *
, Row_Number() over
(partition by IntProcesso, Analista order by ISNULL(seqnum, 0) desc) as RN
from MyResults) a
where RN = 1
This will assign row_number 1 to any rows that came from your first query, or to any rows from the second query that do not have matches in the first query, then filter out extra rows.
You could also use outer joins with isnull or coalesce, as others have suggested. Something like this:
Select ISNULL(a.IntProcesso, b.IntProcesso) as IntProcesso
, ISNULL(a.Analista, b.Analista) as Analista
, ISNULL(a.ETSsigla, b.ETSsigla) as ETSsigla
[repeat for the rest of your columns]
from Table1 a
full outer join Table2 b
on a.IntProcesso = b.IntProcesso and a.Analista = b.Analista
Your code is hard to read, because of the lengthy names of everything (and to be honest, the fact that they're in a language I don't speak also makes it a lot harder).
But how about: replacing your INNER JOINs with LEFT JOINs, adding more LEFT JOINs to draw in the alternative tables, and introducing ISNULL clauses for each variable you want in the results?
If you do something like ... Query1 Right Join Query2 On ... that should get only the rows in Query2 that don't appear in Query 1.

Inner Join and Left Join in same sql query

I'm trying to perform inner join and then left join in same sql query.
But the left join is not working. It is not showing the null values
I've two tables EVENT_INVITATIONS and USERINFO which has 2 records when joined.
so, the join query goes like this :
select * from [UandMePROD].[dbo].EVENT_INVITATIONS EI
join [UandMePROD].[dbo].USERINFO UI on EI.USER_ID = UI.USER_ID and EI.EVENT_ID=11033
It gives out 2 records.
So, I'm performing a left join with another table CLIENT_CONTACTS which has only 1 matching record in it.
So, actually it should show the null value to the unmatched record. but it is not showing the second record. It is showing only 1 record which is matched(join)
My failed sql query :
select * from [UandMePROD].[dbo].EVENT_INVITATIONS EI
join [UandMePROD].[dbo].USERINFO UI on EI.USER_ID = UI.USER_ID
left join CLIENT_CONTACTS CC on UI.MOBILENO=CC.MOBILE_NUMBER
where cc.CLIENT_ID=20111 and EI.EVENT_ID=11033
can you please tell me where I'm doing mistake?
I need the 2 records.
Since you are doing a left join, cc.CLIENT_ID is null for all the values which only exist in CLIENT_CONTACTS and your where clause Where cc.CLIENT_ID = 20111
converts your LEFT JOIN into INNER JOIN. Adding this filter in ON clause solves the issue.
select *
from [UandMePROD].[dbo].EVENT_INVITATIONS EI
inner join [UandMePROD].[dbo].USERINFO UI on EI.[USER_ID] = UI.[USER_ID]
left join CLIENT_CONTACTS CC on UI.MOBILENO = CC.MOBILE_NUMBER
and cc.CLIENT_ID = 20111
where EI.EVENT_ID=11033
You should not specify EI.EVENT_ID on WHERE clause. Those limit your results after the join. You should specify EI.EVENT_ID in an ON clause.
select * from [UandMePROD].[dbo].EVENT_INVITATIONS EI join [UandMePROD].[dbo].USERINFO UI on EI.USER_ID = UI.USER_ID AND (EI.EVENT_ID=11033 or EI.EVENT_ID is null) left join CLIENT_CONTACTS CC on UI.MOBILENO=CC.MOBILE_NUMBER where cc.CLIENT_ID=20111
Providing some suggestions,since it is not possible to say what is happening with out table data
Left join should show null values from output of first inner join eventhough there are no mobile number matches,so try removing where condition and see if you are getting any result

Linq Left outer join Query

How to convert this sql query into Linq query?
select *
from setupUOMs as su
LEFT OUTER JOIN scmSKUUoMs as ssu
on su.UoMID != ssu.UoMID
where ssu.SKUID = 446 and su.UMTypeID = 5
Following is the linq query.
from c in setupUOMs
join o in scmSKUUoMs
on c.UOMID equals o.UoMID into sr
from x in sr.DefaultIfEmpty()
where x.SKUID == 446
select x
In above query I've so far only done to extract the join number but what I want is to select the non equal records of left table but I'm able to show joined record. and it returns the records of only left table while my result is based on both columns. In where clause I can access x.SKUID which is from left table but can't access x.UMTypesID which is form right table (Means no column from right table is returned on which I can make condition).
Take a look at this LEFT JOIN LINQTOSQL Example.
http://www.devcurry.com/2011/01/linq-left-join-example-in-c.html
Maybe it will help.
A join with a non-equals condition is not a join but a Cartesian product excluding the inner joined records. There may be valid reasons to make a query as you did, but there's always a risk of blowing up the result set in terms of number of records.
So let's assume the conditions ensure a result that makes sense, then you can do:
from su in setupUOMs
from ssu in scmSKUUoMs // from .. from is a Cartesian product
where su.UOMID != ssu.UoMID
&& ssu.SKUID == 446
&& su.UMTypeID == 5
select new { su.Prop1, ssu.Prop2, ... }

Resources