Ι have some tables ( eg. [Table1]
, [Table2]
, [Table3]
and so on ) with a [ID]
as primary key and a RecTime
as DATETIME
on each.
Αlso Ι have a table [Files]
that hold files in a varbinary(max)
column, and refers to the other tables having their Names and IDs.
[Table2]
, [Table3]
and others have different structure, but share the [ID]
and [RecTime]
column exactly as in [Table1]
Below is a quick sample to visualize data.
DECLARE @Table1 as table (
[ID] [bigint]
, [RecTime] [datetime]
)
DECLARE @Table2 as table (
[ID] [bigint]
, [RecTime] [datetime]
)
DECLARE @Table3 as table (
[ID] [bigint]
, [RecTime] [datetime]
)
DECLARE @Files as table (
[ID] [bigint]
, [tblName] nvarchar(255) NULL
, [tblID] bigint NULL
, [BinaryData] varbinary(max)
/* and some other columns */
)
INSERT INTO @Table1 (
[ID]
, [RecTime]
)
SELECT '1', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '2', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '3', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '4', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '5', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
INSERT INTO @Table2 (
[ID]
, [RecTime]
)
SELECT '11', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '12', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '13', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '14', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '15', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
INSERT INTO @Table3 (
[ID]
, [RecTime]
)
SELECT '21', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '22', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '23', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '24', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '25', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
INSERT INTO @Files (
[ID]
, [tblName]
, [tblID]
, [BinaryData]
)
SELECT '1', 'Table1', '1', 0x010203040506
UNION ALL SELECT '2', 'Table1', '2', 0x010203040506
UNION ALL SELECT '3', 'Table1', '2', 0x010203040506
UNION ALL SELECT '4', 'Table1', '3', 0x010203040506
UNION ALL SELECT '5', 'Table1', '4', 0x010203040506
UNION ALL SELECT '6', 'Table1', '5', 0x010203040506
UNION ALL SELECT '7', 'Table1', '5', 0x010203040506
UNION ALL SELECT '8', 'Table2', '11', 0x010203040506
UNION ALL SELECT '9', 'Table2', '11', 0x010203040506
UNION ALL SELECT '10', 'Table2', '12', 0x010203040506
UNION ALL SELECT '11', 'Table2', '13', 0x010203040506
UNION ALL SELECT '12', 'Table2', '14', 0x010203040506
UNION ALL SELECT '13', 'Table2', '12', 0x010203040506
UNION ALL SELECT '14', 'Table2', '15', 0x010203040506
UNION ALL SELECT '15', 'Table3', '21', 0x010203040506
UNION ALL SELECT '16', 'Table3', '22', 0x010203040506
UNION ALL SELECT '17', 'Table3', '24', 0x010203040506
UNION ALL SELECT '18', 'Table3', '23', 0x010203040506
UNION ALL SELECT '19', 'Table3', '25', 0x010203040506
UNION ALL SELECT '20', 'Table3', '25', 0x010203040506
UNION ALL SELECT '21', 'Table3', '21', 0x010203040506
SELECT * FROM @Table1
SELECT * FROM @Table2
SELECT * FROM @Table3
SELECT * FROM @Files
How can I join [Files]
table to other tables, the Name
and ID
of which derive from a value in '[Files]' table ?
I need [BinaryData]
from [Files]
table and [RecTime]
from respective table reference in [Files]
table.
The real problem is that [Table1]
, [Table2]
and [Table3]
are not the only tables that are referred [Files]
table. New tables can be created, for which binary data must be stored in [Files]
table.
So I'm looking for a way to "join" them dynamically.
P.S. I'm not the creator of this system, and can not perform any structural change on it, but just trying to solve this problem.
Any help would be appreciated.
This is the simplest way to do the above. No need of looping or any thing. You need dynamic code as Tables can be add at any time.
Note: In your sample data for Files
table seems have wrong data in tblId
?
So I am changing your data to match IDs to respective tables.
Schema:
CREATE TABLE Table1 (
[ID] [bigint]
, [RecTime] [datetime]
)
CREATE TABLE Table2 (
[ID] [bigint]
, [RecTime] [datetime]
)
CREATE TABLE Table3 (
[ID] [bigint]
, [RecTime] [datetime]
)
CREATE TABLE Files (
[ID] [bigint]
, [tblName] nvarchar(255) NULL
, [tblID] bigint NULL
, [BinaryData] varbinary(max)
/* and some other columns */
)
INSERT INTO Table1 (
[ID]
, [RecTime]
)
SELECT '1', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '2', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '3', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '4', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '5', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
INSERT INTO Table2 (
[ID]
, [RecTime]
)
SELECT '11', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '12', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '13', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '14', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '15', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
INSERT INTO Table3 (
[ID]
, [RecTime]
)
SELECT '21', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '22', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '23', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '24', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
UNION ALL SELECT '25', DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)
INSERT INTO Files (
[ID]
, [tblName]
, [tblID]
, [BinaryData]
)
SELECT '1', 'Table1', '1', 0x010203040506
UNION ALL SELECT '2', 'Table1', '2', 0x010203040506
UNION ALL SELECT '3', 'Table1', '2', 0x010203040506
UNION ALL SELECT '4', 'Table1', '3', 0x010203040506
UNION ALL SELECT '5', 'Table1', '4', 0x010203040506
UNION ALL SELECT '6', 'Table1', '5', 0x010203040506
UNION ALL SELECT '7', 'Table1', '5', 0x010203040506
UNION ALL SELECT '8', 'Table2', '11', 0x010203040506
UNION ALL SELECT '9', 'Table2', '11', 0x010203040506
UNION ALL SELECT '10', 'Table2', '12', 0x010203040506
UNION ALL SELECT '11', 'Table2', '13', 0x010203040506
UNION ALL SELECT '12', 'Table2', '14', 0x010203040506
UNION ALL SELECT '13', 'Table2', '12', 0x010203040506
UNION ALL SELECT '14', 'Table2', '15', 0x010203040506
UNION ALL SELECT '15', 'Table3', '21', 0x010203040506
UNION ALL SELECT '16', 'Table3', '22', 0x010203040506
UNION ALL SELECT '17', 'Table3', '24', 0x010203040506
UNION ALL SELECT '18', 'Table3', '23', 0x010203040506
UNION ALL SELECT '19', 'Table3', '25', 0x010203040506
UNION ALL SELECT '20', 'Table3', '25', 0x010203040506
UNION ALL SELECT '21', 'Table3', '21', 0x010203040506
Now your Dynamic Query Part:
DECLARE @QRY VARCHAR(MAX)='', @Tables VARCHAR(MAX)='';
--Capturing List of Table names for selecting RecTime
SELECT @Tables = @Tables+ tblName+'.RecTime,' FROM (
SELECT DISTINCT tblName FROM Files
)A
--To remove last comma
SELECT @Tables = SUBSTRING(@Tables,1, LEN(@Tables)-1)
--Preparing Dynamic Qry
SELECT @QRY = '
SELECT Files.ID,Files.BinaryData
,COALESCE('+@Tables+') AS RecTime
FROM Files '
SELECT @QRY =@QRY+ JOINS FROM (
SELECT DISTINCT '
LEFT JOIN '+ tblName + ' ON Files.tblID = '+tblName+'.ID AND Files.tblName= '''+tblName+''''
as JOINS
FROM Files
)A
print @QRY
EXEC( @QRY)
If you want to see what @Qry
contains
/*
Print Output:
SELECT Files.ID,Files.BinaryData
,COALESCE(Table1.RecTime,Table2.RecTime,Table3.RecTime) AS RecTime
FROM Files
LEFT JOIN Table1 ON Files.tblID = Table1.ID AND Files.tblName= 'Table1'
LEFT JOIN Table2 ON Files.tblID = Table2.ID AND Files.tblName= 'Table2'
LEFT JOIN Table3 ON Files.tblID = Table3.ID AND Files.tblName= 'Table3'
*/