I would like to decide Inner or outer join ( to the same table) depending on the value.
How do I do this?
Thanks
I have all my select values here
Then bunch of joins
And on the last join I would like to do
CASE
WHEN RTRIM(LTRIM(#AccountType)) = 'OFX' THEN
INNER JOIN Subscriber.Access.SubscriberOFXAccount ASOA
ON SSA.Id = ASOA.SubscriberOFXAccountId AND ASOA.Active = 1
ELSE
LEFT JOIN Subscriber.Access.SubscriberOFXAccount ASOA2
ON SSA.Id = ASOA2.SubscriberOFXAccountId
You just use an if/else condition to make up the SQL Statement completly:
IF RTRIM(LTRIM(#AccountType)) = 'OFX' THEN
BEGIN
SELECT Blah FROM Table WHERE Blah2=SomeThings INNER JOIN MyOtherFooBar ON ...
END
ELSE
BEGIN
SELECT Blah FROM Table WHERE Blah2=SomeThings LEFT JOIN MyOtherFooBar ON ...
END
How about:
Select ..
From ...
Left Join Subscriber.Access.SubscriberOFXAccount ASOA
ON SSA.Id = ASOA.SubscriberOFXAccountId
Where RTRIM(LTRIM(#AccountType)) <> 'OFX' Or ASOA.IsActive = 1
Note that by check for IsActive = 1 on a left join, it effectively means a row must exist and thus when #AccountType is not OFX, it will effectively use an inner join.
Related
This is a stored procedure to select the full details of a wine.
It takes as a parameter a storage location ID.
This builds properly and is similar in structure to many sp's I have written that work,
however it returns no data. Is there something I am missing?
CREATE PROCEDURE [sp_retrieveInventory_Full]
(
#StorageLocationID [int]
)
AS
BEGIN
SELECT [WineName],
[RackID],
[RackColumn],
[RackRow],
[WineTypeID],
[WineVarietyID],
[VintnerName],
[dbo].[Vintner].[Country],
[dbo].[Vintner].[StateProvince],
[dbo].[Vintner].[Region],
[VendorName],
[Vintage],
[PurchaseDate],
[PurchasePrice],
[BottleSizeID],
[ABV],
[DrinkByDate],
[FoodType],
[TastingNotes],
[RatedBy],
[RatingScore]
FROM [dbo].[StorageLocation]
INNER JOIN [dbo].[Wine]
ON [dbo].[StorageLocation].[WineID] = [dbo].[Wine].[WineID]
INNER JOIN [dbo].[Vintner]
ON [dbo].[Vintner].[VintnerID] = [dbo].[Wine].[VintnerID]
INNER JOIN [dbo].[Vendor]
ON [dbo].[Vendor].[VendorID] = [dbo].[Wine].[VendorID]
INNER JOIN [dbo].[Pairing]
ON [dbo].[Pairing].[PairingID] = [dbo].[Wine].[PairingID]
INNER JOIN [dbo].[Rating]
ON [dbo].[Rating].[RatingID] = [dbo].[Wine].[RatingID]
WHERE [dbo].[StorageLocation].[StorageLocationID] = #storageLocationID
END
GO
When a query reruns no result it's because no records exists that satisfy the conditions in it's where clause, or, in case of queries that contains inner joins, at least one of the joins on condition returns no records.
The easiest way to figure out what join is messing up your query is to start removing the joins one by one, but to do that, you have to first change the select clause.
What I like to do is this: Start with all the joins except the last one - see if it returns any records:
SELECT 1
FROM [dbo].[StorageLocation]
INNER JOIN [dbo].[Wine]
ON [dbo].[StorageLocation].[WineID] = [dbo].[Wine].[WineID]
INNER JOIN [dbo].[Vintner]
ON [dbo].[Vintner].[VintnerID] = [dbo].[Wine].[VintnerID]
INNER JOIN [dbo].[Vendor]
ON [dbo].[Vendor].[VendorID] = [dbo].[Wine].[VendorID]
INNER JOIN [dbo].[Pairing]
ON [dbo].[Pairing].[PairingID] = [dbo].[Wine].[PairingID]
-- INNER JOIN [dbo].[Rating]
-- ON [dbo].[Rating].[RatingID] = [dbo].[Wine].[RatingID]
WHERE [dbo].[StorageLocation].[StorageLocationID] = #storageLocationID
If not, comment out the next join and run the query again. Rinse and repeat.
Please note, however, that there might be more than one inner join that prevents the query from returning records.
We have many complex queries which involve a lot of columns and joins (see the example below) that are implemented as views.
In some cases these queries return duplicate rows which then have to be programmatically removed by the consuming app. Therefore, we would like to enhance the SQL query to eliminate the duplicates, and speed up the retrieval process.
I know that I can use OVER / PARTITION BY logic to do this, but I am not sure of how to modify the queries to obtain a working syntax.
Here is an example:
SELECT
Main.MfgOrder.OrderNumber,
Main.MfgOrder.DesignBOMID,
Main.Design_Plant.PlantID,
Main.MfgOrder_Operation.OrderOpID,
Main.MfgOrder_Operation.DesignOpID,
Main.MfgOrder_Operation.OpSeq,
Main.MfgOrder_Operation.Description,
Main.MfgOrder_Operation.CompletionStatus,
Main.MfgOrder__Shift.OrderShiftID,
Main.MfgOrder__Shift.WorkCenterMachineID,
Main.MfgOrder___Event.OrderEventID,
Main.MfgOrder____Reel.OrderReelID,
Main.MfgOrder____Reel.ReelNumber,
Main.MfgOrder____Reel.Location,
Main.MfgOrder____Reel.Test_Status AS Test_Status_Reel,
Main.MfgOrder____Reel.Test_Disposition AS Test_Disposition_Reel,
Main.MfgOrder____Reel.LabReleased,
Main.MfgOrder____Reel.ShipReelsBypassSet,
Main.MfgOrder_____Length.OrderLengthID,
Main.MfgOrder_____Length.LengthType,
Main.MfgOrder_____Length.LocationOnReel,
Main.MfgOrder_____Length.LocationOnLength,
Main.MfgOrder_____Length.TrialNumber,
Main.MfgOrder_____Length.SampleNumber,
Main.MfgOrder_____Length.PrintNumber,
Main.MfgOrder_____Length.Test_Status AS Test_Status_Length,
Main.MfgOrder_____Length.Test_Category,
Main.MfgOrder_____Length.Test_Disposition AS Test_Disposition_Length,
Main.MfgOrder_____Length.SampleSubmittedBy,
Main.MfgOrder_____Length.SampleSubmittedDate,
Main.MfgOrder_____Length.BypassTesting,
Main.MfgOrder_____Length_OperatorQty.Sample1Destination,
Main.MfgOrder_____Length_OperatorQty.Sample2Destination,
Main.MfgOrder_____Length_OperatorQty.Sample3Destination,
Main.MfgOrder______Component.OrderComponentID,
Main.MfgOrder______Component.DesignComponentID,
Main.MfgOrder______Component.ItemNo,
Main.MfgOrder_______Test.LabTestID,
Main.MfgOrder_______Test.OrderTestID,
Main.MfgOrder_______Test.TestComplete,
Main.MfgOrder_______Test.TestStatus,
Main.MfgOrder________Marker2.OrderMarkerID,
Master.Color.ColorName,
Master.LabTest.ExcludeFromPassFail,
CASE
WHEN Main.Design_Component.Component_Label IS NULL
THEN 'Unknown'
ELSE Main.Design_Component.Component_Label
END AS Component_Label
FROM
Main.MfgOrder
INNER JOIN
Main.Design__BOM ON Main.MfgOrder.DesignBOMID = Main.Design__BOM.DesignBOMID
INNER JOIN
Main.Design_Plant ON Main.Design__BOM.DesignPlantID = Main.Design_Plant.DesignPlantID
INNER JOIN
Main.MfgOrder_Operation ON Main.MfgOrder.OrderNumber = Main.MfgOrder_Operation.OrderNumber
INNER JOIN
Main.MfgOrder__Shift ON Main.MfgOrder_Operation.OrderOpID = Main.MfgOrder__Shift.OrderOpID
INNER JOIN
Main.MfgOrder___Event ON Main.MfgOrder__Shift.OrderShiftID = Main.MfgOrder___Event.OrderShiftID
INNER JOIN
Main.MfgOrder____Reel ON Main.MfgOrder___Event.OrderEventID = Main.MfgOrder____Reel.OrderEventID
INNER JOIN
Main.MfgOrder_____Length ON Main.MfgOrder____Reel.OrderReelID = Main.MfgOrder_____Length.OrderReelID
LEFT OUTER JOIN
Main.MfgOrder______Component ON Main.MfgOrder_____Length.OrderLengthID = Main.MfgOrder______Component.OrderLengthID
LEFT OUTER JOIN
Main.MfgOrder_______Test ON Main.MfgOrder______Component.OrderComponentID = Main.MfgOrder_______Test.OrderComponentID
LEFT OUTER JOIN
Main.MfgOrder________Marker2 ON Main.MfgOrder_______Test.OrderTestID = Main.MfgOrder________Marker2.OrderTestID
LEFT OUTER JOIN
Main.Design_Component ON Main.MfgOrder______Component.DesignComponentID = Main.Design_Component.DesignComponentID
LEFT OUTER JOIN
Master.Color ON Main.MfgOrder______Component.TapeColorID = Master.Color.ColorNumber
LEFT OUTER JOIN
Master.LabTest ON Main.MfgOrder_______Test.LabTestID = Master.LabTest.LabTestID
LEFT OUTER JOIN
Main.MfgOrder_____Length_OperatorQty ON Main.MfgOrder______Component.OrderLengthID = Main.MfgOrder_____Length_OperatorQty.OrderLengthID
you can use row_number as below: Below query will not select duplicate only on OrderNumber, if you need to add other columns you add accordingly
Select * from (
Select
RowN = Row_Number() over( partition by Main.MfgOrder.OrderNumber order by Main.MfgOrder.OrderNumber),
--- All your select columns and all your query with joins
) a
Where a.RowN = 1
Is the entire row duplicated exactly? If so then just add DISTINCT
SELECT DISTINCT
...
FROM
...
If you are getting duplicate rows where most columns the same but some columns are different then GROUP BY the columns that are the same and select MIN(column_name) for the ones that are causing the extra rows to appear.
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.
Hello I have the below SQL query that I would like to conditionally return results from one of two DB columns (DEA and DEA_ALT) into one result column depending which of those two columns is valued (not null). The DB is setup where there are two fields that can store a field called DEA# however both fields have the same purpose, and therefore I would like to return the results from either column depending on which one is valued (can be either).
SELECT Distinct t1.UserName,
t1.[LoginID],
t7.FirstName,
t7.LastName,
t7.Title ,
t7.EndDateOfValidity,
NPI = ISNULL(HStaffIdentifiers.Value,''),
Type= HStaffIdentifiers.Type,
DEA=ISNULL(t5.PrescriberCode,''),
--
--
DEA_ALT = ISNULL((select CASE ISNULL(PC.PrescriberCode,'')
when '' then ISNULL(HS.Value,'')
end
from HStaff PC
left outer join HStaffIdentifiers HS
ON PC.ObjectID = HS.Staff_oid
where HS.Type = 'DEA'
and HS.Staff_oid = HStaffIdentifiers.Staff_oid
),ISNULL(t5.PrescriberCode,'')),
--
--
Speciality = ISNULL(HDataDictionaryItem3.Description,''),
Preference_Group = HDataDictionaryItem1.Name
FROM HSUser t1 with (nolock)
Left Outer JOIN HStaff t5 with (nolock)
ON t1.UserName=t5.MSINumber
LEFT OUTER JOIN HStaffIdentifiers HStaffIdentifiers WITH (NOLOCK)
ON t5.ObjectID = HStaffIdentifiers.Staff_oid
AND HStaffIdentifiers.Type = 'NPI'
JOIN HPerson t6 with (nolock)
ON t5.ObjectID=t6.ObjectID
JOIN HName t7 with (nolock)
ON t6.ObjectID=t7.Person_oid
and (t7.EndDateOfValidity < '2010-01-01 00:00:00.000'
or t7.EndDateOfValidity is null)
JOIN HDataDictionaryItem HDataDictionaryItem1 WITH (NOLOCK)
ON t1.PreferenceGroup_oid = HDataDictionaryItem1.ObjectID
AND HDataDictionaryItem1.ItemType_oid = 98
left outer join HDataDictionaryItem HDataDictionaryItem3 WITH (NOLOCK)
ON t5.PrimarySpeciality_oid = HDataDictionaryItem3.ObjectID
AND HDataDictionaryItem3.ItemType_oid = 43
WHERE
t1.EndTime >= GETDATE()
AND t1.BeginTime<=GETDATE()
AND t5.Active=1
AND t6.IsDeleted=0
AND t5.StaffType = 0
order by t7.LastName, t7.FirstName
Snippet from the results at the following link:
http://s7.postimg.org/i5xlsjhnv/12_31_2014_10_00_13_AM.jpg
As you can see from the query results (highlighted in red) there are cases when the DEA may only be populated in one of those two columns, however I want the results to be returned to a single column from the DEA column if it is valued, If not, then I want to check to see if DEA_ALT is valued and if so return the result to this single column. How can I accomplish this?
As #NoDisplayName has said you should just use coalesce. From what I can tell though I think it can be a bit simpler. Specifically if you are looking to merge the DEA and DEA_ALT you can take this section
DEA=ISNULL(t5.PrescriberCode,''),
--
--
DEA_ALT = ISNULL((select CASE ISNULL(PC.PrescriberCode,'')
when '' then ISNULL(HS.Value,'')
end
from HStaff PC
left outer join HStaffIdentifiers HS
ON PC.ObjectID = HS.Staff_oid
where HS.Type = 'DEA'
and HS.Staff_oid = HStaffIdentifiers.Staff_oid
),ISNULL(t5.PrescriberCode,'')),
and write it like this
Coalesce(t5.PrescriberCode, HStaffIden.Value) As DEA,
you will need to add a new table for the DEA values like this
LEFT OUTER JOIN HStaffIdentifiers HStaffIden WITH (NOLOCK)
ON HStaffIdentifiers.Staff_oid = HStaffIden.Staff_oid
you can then take this Join Condition
LEFT OUTER JOIN HStaffIdentifiers HStaffIdentifiers WITH (NOLOCK)
ON t5.ObjectID = HStaffIdentifiers.Staff_oid
AND HStaffIdentifiers.Type = 'NPI'
And remove the AND condition like this
LEFT OUTER JOIN HStaffIdentifiers HStaffIdentifiers WITH (NOLOCK)
ON t5.ObjectID = HStaffIdentifiers.Staff_oid
Then add this condition to the where statement to finish the changes
AND HStaffIdentifiers.Type = 'NPI'
And HStaffIden = 'DEA'
Edit: Fixed the result set so that it correctly matches your original query
Looks like you just need Isnull or coalesce
SELECT ...,Isnull(t5.PrescriberCode, (SELECT CASE Isnull(PC.PrescriberCode, '')
WHEN '' THEN Isnull(HS.Value, '')
END
FROM HStaff PC
LEFT OUTER JOIN HStaffIdentifiers HS
ON PC.ObjectID = HS.Staff_oid
WHERE HS.Type = 'DEA'
AND HS.Staff_oid = HStaffIdentifiers.Staff_oid), Isnull(t5.PrescriberCode, ''))
,...
I wish to delete a result a select statement returns, reason I'm doing this is because I have relationships between tables and if I delete from the top-most table its children rows in other tables have to be deleted, too.
Can anyone correct this stored procedure for me please?
ALTER proc [dbo].[storedprocname]
(#Parameter uniqueidentifier = '00000000-0000-0000-0000-000000000000')
AS BEGIN
DELETE FROM TableOne
WHERE IDOne IN
(SELECT
IDOne,
DescOne, IndexOne,
IDTwo,
QuestionTwo, ControlTypeTwo, IndexTwo,
IDThree,
DescThree, IndexThree,
QuestionFour,
OptionFour
FROM
TableOne
INNER JOIN
TableTwo ON TableTwo.CatID = TableOne.IDOne
INNER JOIN
TableThree ON TableThree.Question = TableTwo.IDTwo
LEFT OUTER JOIN
TableFour ON TableFour.Question = TableThree.IDThree
WHERE
TableOne.IDOne = #Parameter)
END
ALTER proc [dbo].[storedprocname]
(#Parameter uniqueidentifier = '00000000-0000-0000-0000-000000000000')
AS BEGIN
DELETE FROM TableOne
WHERE IDOne IN
(SELECT
IDOne
FROM
TableOne
INNER JOIN
TableTwo ON TableTwo.CatID = TableOne.IDOne
INNER JOIN
TableThree ON TableThree.Question = TableTwo.IDTwo
LEFT OUTER JOIN
TableFour ON TableFour.Question = TableThree.IDThree
WHERE
TableOne.IDOne = #Parameter)
END
Since you want to delete all rows where IDOne is in a list of possible values - then you need to make sure the subquery after the IN (...) also returns a single column which can be used to compare! After all, you cannot compare a single IDOne value to the whole list of columns that you're currently returning ....
Try something like this:
ALTER proc [dbo].[storedprocname]
(#Parameter uniqueidentifier = '00000000-0000-0000-0000-000000000000')
AS BEGIN
DELETE FROM TableOne
WHERE IDOne IN
(SELECT
IDOne
FROM
TableOne
INNER JOIN
TableTwo ON TableTwo.CatID = TableOne.IDOne
INNER JOIN
TableThree ON TableThree.Question = TableTwo.IDTwo
LEFT OUTER JOIN
TableFour ON TableFour.Question = TableThree.IDThree
WHERE
TableOne.IDOne = #Parameter)
END
I don't know (your question is too vague and not clear enough) whether all those JOIN's inside the subquery are really needed .... you might need to tweak that to your requirements.