SQL Server: Left Join and unmatch rows are not coming - tsql

I am using left join as a result everything should come from my left table but only matching data coming. I am not able to understand what is wrong in my query or what is missing in it. so please have a look at sample code where anyone can run and reproduce the issue.
create table #tmpModel
(
CSM_ID int,
ID INT,
ParentID INT,
DisplayInCSM Varchar(200),
Type varchar(20),
LineItemID INT
)
create table #tmpLineItem
(
ID INT,
LineItem Varchar(200),
TickerID varchar(20),
)
create table #tmpOutputDetl_CSMTuner
(
Section Varchar(200),
LineItem Varchar(200),
Period Varchar(200),
ItemValue Decimal(18,2),
Ticker varchar(20)
)
INSERT INTO #tmpModel(CSM_ID,ID,ParentID,DisplayInCSM,Type,LineItemID)
VALUES (370,1,0,'Model','SHEET',0)
,(370,2,1,'Segment Details','GROUP',0)
,(370,3,2,'LoyaltyOne','GROUP',0)
,(370,4,3,'Revenue','LINEITEM',198359)
,(370,5,4,'EBITDA','LINEITEM',198360)
,(370,6,5,'Card Services','GROUP',0)
,(370,7,6,'Diluted','LINEITEM',198342)
INSERT INTO #tmpLineItem(ID,LineItem,TickerID)
VALUES (198359,'Net Revenue','ADK')
,(198360,'EBITDA Details','ADK')
,(198342,'Diluted Shares','ADK')
INSERT INTO #tmpOutputDetl_CSMTuner (Section,LineItem,Period,ItemValue,Ticker)
VALUES ('Consensus Model','Net Revenue','2010 FYA',203.22,'ADS')
,('Consensus Model','Net Revenue','2011 FYA',203.22,'ADS')
,('Consensus Model','Net Revenue','2012 FYA',203.22,'ADS')
,('Consensus Model','EBITDA Details','2010 FYA',103.22,'ADS')
,('Consensus Model','EBITDA Details','2011 FYA',109.22,'ADS')
,('Consensus Model','EBITDA Details','2012 FYA',105.22,'ADS')
,('Key Financial','Diluted Shares','2010 FYA',55.22,'ADS')
,('Key Financial','Diluted Shares','2011 FYA',20.22,'ADS')
,('Key Financial','Diluted Shares','2012 FYA',13.22,'ADS')
;with DirectReports as
(
select CSM_ID,
ID,
ParentID,
hierarchy = format(id,'0000'),
level = 0,
DisplayInCSM,
Type,
LineItemID
from #tmpModel
where isnull(ParentID, 0) = 0
union all
select e.CSM_ID,
e.ID,
e.ParentID,
hierarchy = d.hierarchy + '.' + format(e.id,'0000'),
level = level + 1,
e.DisplayInCSM,
e.Type,
e.LineItemID
from #tmpModel e
join DirectReports d on e.ParentID = d.ID
)
/*SELECT * FROM DirectReports Order By hierarchy*/
,Cte1 as
(
SELECT AA.Section,AA.LineItem,AA.Ticker, r.DisplayInCSM, r.Type,r.hierarchy, AA.ItemValue, AA.Period
FROM DirectReports r
LEFT OUTER JOIN
(
Select b.*,L.ID AS LineItemID,L.TickerID
From #tmpOutputDetl_CSMTuner b
INNER JOIN #tmpLineItem L ON b.LineItem= L.LineItem
WHERE L.TickerID='ADK' AND b.Ticker='ADS'
) AA
ON (AA.LineItemID=r.LineItemID)
WHERE AA.Ticker = 'ADS'
)
SELECT * FROM Cte1 ORDER By hierarchy
IF OBJECT_ID(N'tempdb..#tmpModel') IS NOT NULL
BEGIN
DROP TABLE #tmpModel
END
IF OBJECT_ID(N'tempdb..#tmpLineItem') IS NOT NULL
BEGIN
DROP TABLE #tmpLineItem
END
IF OBJECT_ID(N'tempdb..#tmpOutputDetl_CSMTuner') IS NOT NULL
BEGIN
DROP TABLE #tmpOutputDetl_CSMTuner
END
Data should come with Parent child hierarchy wise
Type Group should come but not coming, only Line Item is coming.
Please guide me which area i should rectify to get the desired output.

Solved this way comment this line /WHERE AA.Ticker = 'ADS'/
Now right data is coming.
create table #tmpModel
(
CSM_ID int,
ID INT,
ParentID INT,
DisplayInCSM Varchar(200),
Type varchar(20),
LineItemID INT
)
create table #tmpLineItem
(
ID INT,
LineItem Varchar(200),
TickerID varchar(20),
)
create table #tmpOutputDetl_CSMTuner
(
Section Varchar(200),
LineItem Varchar(200),
Period Varchar(200),
ItemValue Decimal(18,2),
Ticker varchar(20)
)
INSERT INTO #tmpModel(CSM_ID,ID,ParentID,DisplayInCSM,Type,LineItemID)
VALUES (370,1,0,'Model','SHEET',0)
,(370,2,1,'Segment Details','GROUP',0)
,(370,3,2,'LoyaltyOne','GROUP',0)
,(370,4,3,'Revenue','LINEITEM',198359)
,(370,5,4,'EBITDA','LINEITEM',198360)
,(370,6,5,'Card Services','GROUP',0)
,(370,7,6,'Diluted','LINEITEM',198342)
INSERT INTO #tmpLineItem(ID,LineItem,TickerID)
VALUES (198359,'Net Revenue','ADK')
,(198360,'EBITDA Details','ADK')
,(198342,'Diluted Shares','ADK')
INSERT INTO #tmpOutputDetl_CSMTuner (Section,LineItem,Period,ItemValue,Ticker)
VALUES ('Consensus Model','Net Revenue','2010 FYA',203.22,'ADS')
,('Consensus Model','Net Revenue','2011 FYA',203.22,'ADS')
,('Consensus Model','Net Revenue','2012 FYA',203.22,'ADS')
,('Consensus Model','EBITDA Details','2010 FYA',103.22,'ADS')
,('Consensus Model','EBITDA Details','2011 FYA',109.22,'ADS')
,('Consensus Model','EBITDA Details','2012 FYA',105.22,'ADS')
,('Key Financial','Diluted Shares','2010 FYA',55.22,'ADS')
,('Key Financial','Diluted Shares','2011 FYA',20.22,'ADS')
,('Key Financial','Diluted Shares','2012 FYA',13.22,'ADS')
;with DirectReports as
(
select CSM_ID,
ID,
ParentID,
hierarchy = format(id,'0000'),
level = 0,
DisplayInCSM,
Type,
LineItemID
from #tmpModel
where isnull(ParentID, 0) = 0
union all
select e.CSM_ID,
e.ID,
e.ParentID,
hierarchy = d.hierarchy + '.' + format(e.id,'0000'),
level = level + 1,
e.DisplayInCSM,
e.Type,
e.LineItemID
from #tmpModel e
join DirectReports d on e.ParentID = d.ID
)
/*SELECT * FROM DirectReports Order By hierarchy*/
,Cte1 as
(
SELECT AA.Section,AA.LineItem,AA.Ticker, r.DisplayInCSM, r.Type,r.hierarchy, AA.ItemValue, AA.Period
FROM DirectReports r
LEFT OUTER JOIN
(
Select b.*,L.ID AS LineItemID,L.TickerID
From #tmpOutputDetl_CSMTuner b
INNER JOIN #tmpLineItem L ON b.LineItem= L.LineItem
WHERE L.TickerID='ADK' AND b.Ticker='ADS'
) AA
ON (AA.LineItemID=r.LineItemID)
/*WHERE AA.Ticker = 'ADS'*/
)
SELECT * FROM Cte1 WHERE TYPE <> 'SHEET' ORDER By hierarchy
IF OBJECT_ID(N'tempdb..#tmpModel') IS NOT NULL
BEGIN
DROP TABLE #tmpModel
END
IF OBJECT_ID(N'tempdb..#tmpLineItem') IS NOT NULL
BEGIN
DROP TABLE #tmpLineItem
END
IF OBJECT_ID(N'tempdb..#tmpOutputDetl_CSMTuner') IS NOT NULL
BEGIN
DROP TABLE #tmpOutputDetl_CSMTuner
END

Related

How to populate a column in a table with a string of concatenated values from a column in another table

I'm trying to populate a column in a table with a string of concatenated values from a column in another table. There are numerous solutions suggested, such as How to concatenate text from multiple rows into a single text string in SQL Server, which has 47 answers, but none of them are working for me.
Table #tbl1:
DECLARE #tbl1 TABLE ([Id] INT, [Value] VARCHAR(10))
INSERT INTO #tbl1 ([Id]) VALUES (1),(2),(3)
[Id] [Value]
1 NULL
2 NULL
3 NULL
Table #tbl2:
DECLARE #tbl2 TABLE ([Id] INT, [Value] VARCHAR(10))
INSERT INTO #tbl2 ([Id],[Value]) VALUES (1,'A'),(3,'B'),(1,'C'),(2,'D'),(2,'E'),(3,'F'),(1,'G')
[Id] [Value]
1 A
3 B
1 C
2 D
2 E
3 F
1 G
I'm seeking the syntax to update the records in table #tbl1 to this:
[Id] [Value]
1 ACG
2 DE
3 BF
This doesn't work:
UPDATE [t1]
SET [t1].[Value] = COALESCE([t1].[Value],'') + [t2].[Value]
FROM #tbl1 AS [t1]
LEFT JOIN #tbl2 AS [t2] ON [t1].[Id] = [t2].[Id]
Result:
[Id] [Value]
1 A
2 D
3 B
This syntax produces the same result:
UPDATE [t1]
SET [t1].[Value] = [t2].[Val]
FROM #tbl1 AS [t1]
OUTER APPLY (
SELECT COALESCE([tb2].[Value],[t1].[Value]) AS [Val]
FROM #tbl2 AS [tb2]
WHERE [tb2].[Id] = [t1].[Id]
) AS [t2]
Changing SET to SELECT (below), as in most of the accepted answers, results in the error messages Invalid object name 't1' and Incorrect syntax near 'SELECT'. Expecting SET.
UPDATE [t1]
SELECT [t1].[Value] = COALESCE([t1].[Value],'') + [t2].[Value]
FROM #tbl1 AS [t1]
LEFT JOIN #tbl2 AS [t2] ON [t1].[Id] = [t2].[Id]
My experiments with XML PATH, based upon other Stack Overflow responses (How to concatenate text from multiple rows into a single text string in SQL Server), also produce syntax errors or incorrect results.
Can someone offer the correct syntax?
You have to group the rows, use string_agg to get the values together, and then run the update:
select ##version;DECLARE #tbl1 TABLE ([Id] INT, [Value] VARCHAR(10))
INSERT INTO #tbl1 ([Id]) VALUES (1),(2),(3)
DECLARE #tbl2 TABLE ([Id] INT, [Value] VARCHAR(10))
INSERT INTO #tbl2 ([Id],[Value]) VALUES (1,'A'),(3,'B'),(1,'C'),(2,'D'),(2,'E'),(3,'F'),(1,'G')
;with grouped_data as (
select tbl1.Id, STRING_AGG(tbl2.[Value], '') as value_aggregated
from #tbl1 tbl1
inner join #tbl2 tbl2 on tbl1.Id=tbl2.Id
group by tbl1.id
)
update tbl1 set [Value]=value_aggregated
from #tbl1 tbl1
inner join grouped_data gd on gd.Id=tbl1.id
select * from #tbl1
You can check it running on this DB Fiddle

Issue with PK violation on insert

I have a scenario where almost all of the tables have issues with the PK value as follows. This results is a database error or the violation of the PK insert.
When using the DBCC CheckIdent it displays an inconsistency between the next value and the current one.
Can anyone have a reason for the mismatch happening on several tables?
Since this database is then replicate, I'm afraid this error will propagate across the environment.
I adapted this script to fix it, but really trying to figure out the root of the problem.
/** Version 3.0 **/
if object_id('tempdb..#temp') is not null
drop table #temp
;
with cte as (
SELECT
distinct
A.TABLE_CATALOG AS CATALOG,
A.TABLE_SCHEMA AS "SCHEMA",
A.TABLE_NAME AS "TABLE",
B.COLUMN_NAME AS "COLUMN",
IDENT_SEED (A.TABLE_NAME) AS Seed,
IDENT_INCR (A.TABLE_NAME) AS Increment,
IDENT_CURRENT (A.TABLE_NAME) AS Curr_Value
, DBPS.row_count AS NumberOfRows
FROM INFORMATION_SCHEMA.TABLES A
inner join INFORMATION_SCHEMA.COLUMNS B on b.TABLE_NAME = a.TABLE_NAME and b.TABLE_SCHEMA = a.TABLE_SCHEMA
inner join sys.identity_columns IC on OBJECT_NAME (IC.object_id) = a.TABLE_NAME
inner join sys.dm_db_partition_stats DBPS ON DBPS.object_id =IC.object_id
inner join sys.indexes as IDX ON DBPS.index_id =IDX.index_id
WHERE A.TABLE_CATALOG = B.TABLE_CATALOG AND
A.TABLE_SCHEMA = B.TABLE_SCHEMA AND
A.TABLE_NAME = B.TABLE_NAME AND
COLUMNPROPERTY (OBJECT_ID (B.TABLE_NAME), B.COLUMN_NAME, 'IsIdentity') = 1 AND
OBJECTPROPERTY (OBJECT_ID (A.TABLE_NAME), 'TableHasIdentity') = 1 AND
A.TABLE_TYPE = 'BASE TABLE'
)
select 'DBCC CHECKIDENT ('''+A.[SCHEMA]+'.'+a.[TABLE]+''', reseed)' command
, ROW_NUMBER() OVER(ORDER BY a.[SCHEMA], a.[TABLE] asc) AS ID
, A.Curr_Value
, a.[TABLE]
into #temp
from cte A
ORDER BY A.[SCHEMA], A.[TABLE]
declare #i int = 1, #count int = (select max(ID) from #temp)
declare #text varchar(max) = ''
select #COUNT= count(1) FROM #temp
WHILE #I <= #COUNT
BEGIN
SET #text = (SELECT command from #temp where ID=#I)
EXEC (#text + ';')
print #text
select Curr_Value OldValue, ident_current([TABLE]) FixValue, [TABLE] from #temp where ID=#I
SET #I = #I + 1
SET #text='';
END
go
maybe someone or something with enough permissions made a mistake by reseeding?
As simple as this:
create table testid (
id int not null identity (1,1) primary key,
data varchar (3)
)
insert into testid (data) values ('abc'),('cde')
DBCC CHECKIDENT ('testid', RESEED, 1)
insert into testid (data) values ('bad')

sql recursion: find tree given middle node

I need to get a tree of related nodes given a certain node, but not necessary top node. I've got a solution using two CTEs, since I am struggling to squeeze it all into one CTE :). Might somebody have a sleek solution to avoid using two CTEs? Here is some code that I was playing with:
DECLARE #temp AS TABLE (ID INT, ParentID INT)
INSERT INTO #temp
SELECT 1 ID, NULL AS ParentID
UNION ALL
SELECT 2, 1
UNION ALL
SELECT 3, 2
UNION ALL
SELECT 4, 3
UNION ALL
SELECT 5, 4
UNION ALL
SELECT 6, NULL
UNION ALL
SELECT 7, 6
UNION ALL
SELECT 8, 7
DECLARE #startNode INT = 4
;WITH TheTree (ID,ParentID)
AS (
SELECT ID, ParentID
FROM #temp
WHERE ID = #startNode
UNION ALL
SELECT t.id, t.ParentID
FROM #temp t
JOIN TheTree tr ON t.ParentID = tr.ID
)
SELECT * FROM TheTree
;WITH Up(ID,ParentID)
AS (
SELECT t.id, t.ParentID
FROM #temp t
WHERE t.ID = #startNode
UNION ALL
SELECT t.id, t.ParentID
FROM #temp t
JOIN Up c ON t.id = c.ParentID
)
--SELECT * FROM Up
,TheTree (ID,ParentID)
AS (
SELECT ID, ParentID
FROM Up
WHERE ParentID is null
UNION ALL
SELECT t.id, t.ParentID
FROM #temp t
JOIN TheTree tr ON t.ParentID = tr.ID
)
SELECT * FROM TheTree
thanks
Meh. This avoids using two CTEs, but the result is a brute force kludge that hardly qualifies as "sleek" as it won’t be efficient if your table is at all sizeable. It will:
Recursively build all possible hierarchies
As you build them, flag the target NodeId as you find it
Return only the targeted tree
I threw in column “TreeNumber” on the off-chance the TargetId appears in multiple hierarchies, or if you’d ever have multiple values to check in one pass. “Depth” was added to make the output a bit more legible.
A more complex solution like #John’s might do, and more and subtler tricks could be done with more detailed table sturctures.
DECLARE #startNode INT = 4
;WITH cteAllTrees (TreeNumber, Depth, ID, ParentID, ContainsTarget)
AS (
SELECT
row_number() over (order by ID) TreeNumber
,1
,ID
,ParentID
,case
when ID = #startNode then 1
else 0
end ContainsTarget
FROM #temp
WHERE ParentId is null
UNION ALL
SELECT
tr.TreeNumber
,tr.Depth + 1
,t.id
,t.ParentID
,case
when tr.ContainsTarget = 1 then 1
when t.ID = #startNode then 1
else 0
end ContainsTarget
FROM #temp t
INNER JOIN cteAllTrees tr
ON t.ParentID = tr.ID
)
SELECT
TreeNumber
,Depth
,ID
,ParentId
from cteAllTrees
where TreeNumber in (select TreeNumber from cteAllTrees where ContainsTarget = 1)
order by
TreeNumber
,Depth
,ID
Here is a technique where you can select the entire hierarchy, a specific node with all its children, and even a filtered list and how they roll.
Note: See the comments next to the DECLAREs
Declare #YourTable table (id int,pt int,name varchar(50))
Insert into #YourTable values
(1,null,'1'),(2,1,'2'),(3,1,'3'),(4,2,'4'),(5,2,'5'),(6,3,'6'),(7,null,'7'),(8,7,'8')
Declare #Top int = null --<< Sets top of Hier Try 2
Declare #Nest varchar(25) = '|-----' --<< Optional: Added for readability
Declare #Filter varchar(25) = '' --<< Empty for All or try 4,6
;with cteP as (
Select Seq = cast(1000+Row_Number() over (Order by name) as varchar(500))
,ID
,pt
,Lvl=1
,name
From #YourTable
Where IsNull(#Top,-1) = case when #Top is null then isnull(pt,-1) else ID end
Union All
Select Seq = cast(concat(p.Seq,'.',1000+Row_Number() over (Order by r.name)) as varchar(500))
,r.ID
,r.pt
,p.Lvl+1
,r.name
From #YourTable r
Join cteP p on r.pt = p.ID)
,cteR1 as (Select *,R1=Row_Number() over (Order By Seq) From cteP)
,cteR2 as (Select A.Seq,A.ID,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.ID )
Select Distinct
A.R1
,B.R2
,A.ID
,A.pt
,A.Lvl
,name = Replicate(#Nest,A.Lvl-1) + A.name
From cteR1 A
Join cteR2 B on A.ID=B.ID
Join (Select R1 From cteR1 where IIF(#Filter='',1,0)+CharIndex(concat(',',ID,','),concat(',',#Filter+','))>0) F on F.R1 between A.R1 and B.R2
Order By A.R1

Compare rows and multiple columns within same table SQL Server 2012

Compare rows within same table in SQL Server 2012.
Given a table (see script below), what would be the best way to compare rows (individual columns) within the same table?
Example
We are importing data from a client and this can be done many times and we should be able to detect the difference in column's values.
So each time we get the data and we import it we increment our "DataCut" column and then I should be able to compare the difference between datacuts.
If you notice in my sample data in datacutId 3 the Name-Postcode-Homephone have changed.
How would I report on these differences? Any snippet sql or line of thoughts?
Many thanks
SQL script to create test environment
IF EXISTS (SELECT * FROM sys.databases WHERE name='TestDatabase')
BEGIN
ALTER DATABASE TestDatabase
SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE TestDatabase
END
CREATE DATABASE TestDatabase collate Latin1_General_CI_AS
GO
ALTER DATABASE TestDatabase SET RECOVERY SIMPLE
BEGIN TRANSACTION
USE TestDatabase
IF OBJECT_ID(N'[dbo].[Customer]', 'U') IS NOT NULL
DROP TABLE [dbo].[Customer];
GO
CREATE TABLE [dbo].[Customer](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[DataCutId] [int] NOT NULL,
[CustomerId] [int] NOT NULL,
[Name] [varchar](50) NULL,
[Surname] [varchar](50) NULL,
[City] [varchar](255) NULL,
[PostCode] [varchar](10) NULL,
[HomePhone] [varchar](50) NULL,
CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[Customer] ON;
INSERT INTO [dbo].[Customer]([Id], [DataCutId],CustomerId, [Name], [Surname], [City], [PostCode], [HomePhone])
SELECT 1, 1,20, N'Jo', N'Bloggs', N'London', N'aaa 342', N'0207 3456785' UNION ALL
SELECT 2, 2, 20,N'Jo', N'Bloggs', N'London', N'aaa 342', N'0207 3456785' UNION ALL
SELECT 3, 3, 20,N'Mark', N'Bloggs', N'Londong', N'bbb d4543', N'0208 3456785'
SET IDENTITY_INSERT [dbo].[Customer] OFF;
COMMIT
Would this give you a start to solving your problem?
I am sure there might be an easier way maybe?
select a.*, b.DataCutId as UpdDataCutID, b.Name as UpdName, b.Surname as UpdSurname, b.City as UpdCity, b.PostCode as UpdPostCode, b.HomePhone as UpdHomePhone
from Customer a inner join Customer b on a.CustomerId = b.CustomerId
and a.Id < b.ID and a.Name <> b.Name
union
select a.*, b.DataCutId, b.Name, b.Surname, b.City, b.PostCode, b.HomePhone
from Customer a inner join Customer b on a.CustomerId = b.CustomerId
and a.Id < b.ID and a.Surname <> b.Surname
union
select a.*, b.DataCutId, b.Name, b.Surname, b.City, b.PostCode, b.HomePhone
from Customer a inner join Customer b on a.CustomerId = b.CustomerId
and a.Id < b.ID and a.City <> b.City
union
select a.*, b.DataCutId, b.Name, b.Surname, b.City, b.PostCode, b.HomePhone
from Customer a inner join Customer b on a.CustomerId = b.CustomerId
and a.Id < b.ID and a.PostCode <> b.PostCode
union
select a.*, b.DataCutId, b.Name, b.Surname, b.City, b.PostCode, b.HomePhone
from Customer a inner join Customer b on a.CustomerId = b.CustomerId
and a.Id < b.ID and a.HomePhone <> b.HomePhone
EDIT I've pulled this all together in a single query below
select a.*, b.DataCutId as UpdDataCutID, b.Name as UpdName, b.Surname as UpdSurname, b.City as UpdCity, b.PostCode as UpdPostCode, b.HomePhone as UpdHomePhone
from Customer a inner join Customer b on a.CustomerId = b.CustomerId
and a.Id < b.ID and
(a.Name <> b.Name OR
a.Surname <> b.Surname OR
a.City <> b.City OR
a.PostCode <> b.PostCode OR
a.HomePhone <> b.HomePhone)

Can I Choose Different Table for inner join operation?

This is my T-SQL
select Id,Profile,Type ,
case Profile
when 'Soft' then 'SID'
when 'Hard' then 'HID'
end as [Profile]
from ProductDetail p1
inner join [tableA or tableB] on xxxxxxxx
I want join tableA when Profile = Soft and join tableB when Profile = Hard, how can I do just only using T-SQL in one batch?
Thanks
You can't directly do it, but could achieve the same effect with outer joins
select Id,Profile,Type ,
case Profile
when 'Soft' then 'SID'
when 'Hard' then 'HID'
end as [Profile]
from ProductDetail p1
left outer join tableA ON tableA.x = p1.x AND p1.Profile = 'Soft'
left outer join tableB ON tableB.x = p1.x AND p1.Profile = 'Hard'
where
where
(tableA.x IS NOT NULL and p1.Profile = 'Soft')
or (tableB.x IS NOT NULL and p1.Profile = 'Hard')
Of course, you can choose different tables for inner join operation, but it must be based on some condition or variable.
For Example:
select Id,Profile,Type ,
case Profile
when 'Soft' then 'SID'
when 'Hard' then 'HID'
end as [Profile]
from ProductDetail p1
inner join tableA A
on Profile='Soft'
AND <any other Condition>
UNION
select Id,Profile,Type ,
case Profile
when 'Soft' then 'SID'
when 'Hard' then 'HID'
end as [Profile]
from ProductDetail p1
inner join tableB B
on Profile='Hard'
AND <any other Condition>
You can do this in a single statement with the same or similar case statement in your join. Below is sample code using temp tables that joins to 2 different reference tables merged into a single result set using a UNION
DECLARE #ProductDetail TABLE (Id INT, sProfile VARCHAR(100), StID INT, HdID INT)
DECLARE #TableA TABLE (StId INT, Field1 VARCHAR(100))
DECLARE #TableB TABLE (HdId INT, Field1 VARCHAR(100))
INSERT INTO #ProductDetail (Id, sProfile, StID , HdID ) VALUES (1,'Soft',1,1)
INSERT INTO #ProductDetail (Id, sProfile, StID , HdID ) VALUES (2,'Hard',2,2)
INSERT INTO #TableA (StId,Field1) VALUES (1,'Soft 1')
INSERT INTO #TableA (StId,Field1) VALUES (2,'Soft 2')
INSERT INTO #TableB (HdId,Field1) VALUES (1,'Hard 1')
INSERT INTO #TableB (HdId,Field1) VALUES (2,'Hard 2')
SELECT
p1.Id,p1.sProfile,
CASE
WHEN p1.sProfile = 'Soft' THEN StID
WHEN p1.sProfile = 'Hard' THEN HdId
END AS [Profile]
,ReferenceTable.FieldName
FROM
#ProductDetail p1
INNER JOIN
(
SELECT StID AS id, 'Soft' AS sProfile, Field1 AS FieldName
FROM #TableA AS tableA
UNION ALL
SELECT HdID AS id, 'Hard' AS sProfile, Field1 AS FieldName
FROM #TableB AS tableB
)
AS ReferenceTable
ON
CASE
WHEN p1.sProfile = 'Soft' THEN StID
WHEN p1.sProfile = 'Hard' THEN HdID
END = ReferenceTable.Id
AND p1.sProfile = ReferenceTable.sProfile
This will return the following result set:
Id sProfile Profile FieldName
1 Soft 1 Soft 1
2 Hard 2 Hard 2