简体   繁体   中英

Select value from a table name where table name is stored as a value in column in some other table using dynamic SQL?

I am trying to fetch a value for NULL column value. The corresponding value is stored in a different table. This table name is in the same table from which I am trying to fetch

ID  | ColumnName1 | ColumnName2 | ColumnNam3
____________________________________________
1      ABC           TableName1    RecordId1
2      PQR           TableName1    RecordID2
3      NULL          TableName1    RecordId3
4      NULL          TableName2    RecordId1
5      STU           TableName2    RecordId2

So my select query is

Select ColumnName1 from Table

Which is the result

ID  | ColumnName1 | ColumnName2 | ColumnNam3
    ____________________________________________
    1      ABC           TableName1    RecordId1
    2      PQR           TableName1    RecordID2
    3      NULL          TableName1    RecordId3
    4      NULL          TableName2    RecordId1
    5      STU           TableName2    RecordId2

Is it possible to achieve the below?

 Select 
       CASE WHEN ColumnName1 is NULL 
        then SELECT ColumnName1 From ColumnName2 Where RecordId = ColumnName3 
       ELSE COlumnName1 AS 
ColumnNullFilled END

Ohh, I already tried dynamic sql like

Declare @SqlQuery NVARCHAR(MAX)

SET @SqlQuery = N'Select  CASE WHEN ColumnName1 is NULL 
            then SELECT ColumnName1 From ColumnName2 Where RecordId = ColumnName3 
           ELSE COlumnName1 AS 
    ColumnNullFilled1 END 
  Case when ColumnNameSOmeother is NULL
    then SELECT ColumnNameSOmeother  From ColumnName2 Where RecordId = ColumnName3 
           ELSE ColumnNameSOmeother AS 
    ColumnNullFilled2 END  

...
ColumnNameN
FROM Table'

EXEC sp_executesql @SqlQuery;

It does not execute, but only prints columnname2 and columnname3 instead of columnvalues.

For note: I have created a SP that fetches the records based on the columnname2 and ColumnName2 as parameters, which gives the result but does not work with dynamic SQL.

I also tried user defined function, which I am not sure if there is any other way. Here not only 3 records but I am talking about 1000 records and every record has a value in some other table if its null.

Sorry, normalization wasn't done previously by other developer and I cannot go back and change the architecture. Also, the application becomes too heavy if I do it for not just one column but same scenario for different other columns too. (ColumnNameX).

Assuming I understand your requirement, could you not just outer-join both tables and either isnull the column from both tables or use case to determine which column to use?

select IsNull(t1.columnName1, t2.columnName1) as Result
from MyTable t
left join Tablename1 t1 on t1.recordId=ColumnNam3
left join Tablename2 t2 on t2.recordId=ColumnNam3
where <criteria>

or

select case ColumnName2
        when 'TableName1' then t1.ColumnName1 else t2.ColumnName1 end as Result
from MyTable t
left join Tablename1 t1 on t1.recordId=ColumnNam3
left join Tablename2 t2 on t2.recordId=ColumnNam3
where <criteria>

Try the following:

(I included the code to create some test data like in your example)

The actual statement generation is at the bottom.

Basically, this dynamically generates an SQL statement that does left joins on all referenced tables. However, please beware that left joins cause a significant performance problem if there are a lot of them and there are a lot of rows in your tables. In that case I would suggest to rethink your design. For example, split the column ColumnName2 & 3 into several columns...

-- CREATE TEST DATA
create table [Table] (
    [ID] int not null,
    [ColumnName1] varchar(16) null,
    [ColumnName2] sysname not null,
    [ColumnName3] varchar(16) not null
);
go
create table [TableName1] (
    [ColumnName1] varchar(16) null,
    [RecordId] varchar(16) not null
);
go
create table [TableName2] (
    [ColumnName1] varchar(16) null,
    [RecordId] varchar(16) not null
);
go
insert into [Table] ( [ID], [ColumnName1], [ColumnName2], [ColumnName3] )
values
    ( 1, 'ABC', 'TableName1', 'RecordId1' ),
    ( 2, 'PQR', 'TableName1', 'RecordID2' ),
    ( 3, NULL,  'TableName1', 'RecordId3' ),
    ( 4, NULL,  'TableName2', 'RecordId1' ),
    ( 5, 'STU', 'TableName2', 'RecordId2' );
insert into [TableName1] ( [ColumnName1], [RecordId] )
values
    ( '111', 'RecordId1' ),
    ( '222', 'RecordID2' ),
    ( '333', 'RecordId3' );
insert into [TableName2] ( [ColumnName1], [RecordId] )
values
    ( 'one', 'RecordId1' ),
    ( 'two', 'RecordId2' );
go

-- ACTUAL CODE
declare @joinSql nvarchar(max) = N'';
select @joinSql = @joinSql+N'
left join ['+REPLACE([ColumnName2], N']', N'[]]')+N'] on
    [base].[ColumnName2] = N'''+REPLACE([ColumnName2], N'''', N'''''')+N''' and
    ['+REPLACE([ColumnName2], N']', N'[]]')+N'].[RecordId] = [base].[ColumnName3]'
from ( select distinct [ColumnName2] from [Table] ) as [distinct];

declare @caseSql nvarchar(max) = N'';
select @caseSql = @caseSql+N', ['+REPLACE([ColumnName2], N']', N'[]]')+N'].[ColumnName1]'
from ( select distinct [ColumnName2] from [Table] ) as [distinct];

declare @sql nvarchar(max);
set @sql = N'
select
    [base].[ID],
    COALESCE([base].[ColumnName1]'+@caseSql+N') [ColumnName1],
    [base].[ColumnName2],
    [base].[ColumnName3]
from [Table] as [base]'+@joinSql+N';';
print @sql;
exec sp_executesql @sql;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM