admin管理员组文章数量:1122832
I have a situation where I have a couple of tables (TblA
and TblB
) that link together to start a record. I then have a set of tables (TblSet1_A, TblSet1_B, TblSet1_C,
etc.) that hold values linked by another table, tblLink
.
The tblLink
has:
Key_Val
: key value to find intblSet
tablesType
: determines which set of tables to look at (1 = TblSet1, 2 = TblSet2, etc.)DataType
: determines which table of a set to look at (1=_A, 2=_B or _C)Length
: max length of value (if type = 2 and <= 255 then =_B else _C)Description
: attribute description
Example TblLink
entry:
Key_Val | Type | DataType | Length | Description |
---|---|---|---|---|
4 | 1 | 2 | 200 | Item 4 |
I have a situation where I have a couple of tables (TblA
and TblB
) that link together to start a record. I then have a set of tables (TblSet1_A, TblSet1_B, TblSet1_C,
etc.) that hold values linked by another table, tblLink
.
The tblLink
has:
Key_Val
: key value to find intblSet
tablesType
: determines which set of tables to look at (1 = TblSet1, 2 = TblSet2, etc.)DataType
: determines which table of a set to look at (1=_A, 2=_B or _C)Length
: max length of value (if type = 2 and <= 255 then =_B else _C)Description
: attribute description
Example TblLink
entry:
Key_Val | Type | DataType | Length | Description |
---|---|---|---|---|
4 | 1 | 2 | 200 | Item 4 |
This would indicate the Key_Val = 4, tblSet table is tblSet1_B, attribute name 'Key_Val 4'.
Example TblSet1_B Entry:
ID | Key_Val | Value |
---|---|---|
1 | 4 | Value 4 |
If I manually go through the system and map everything, I can write a query like this.
Note: TblLink Type = 1 indicates matching with TblA.ID, Type = 2 matches with TblB.ID.
SELECT
a.ID AS A_ID,
a.LINKID,
b.ID AS B_ID,
b.OTHER,
(SELECT [Value]
FROM TblSet1_B
WHERE [ID] = a.ID AND [KEY_VAL] = 4) AS item_4,
(SELECT [Value]
FROM TblSet2_A
WHERE [ID] = b.ID AND [KEY_VAL] = 7) AS item_7
FROM
TblA a
JOIN
TblB b ON (a.LINKID = B.LINKID);
Output would be like (using table data not shown above, see full example link):
A_ID | LINKID | B_ID | OTHER | item_4 | item_7 |
---|---|---|---|---|---|
1 | 100 | 1 | ID3 | Value 4 | null |
2 | 200 | 2 | ID4 | null | 50 |
2 | 200 | 3 | ID5 | null | null |
Is there a way to dynamically do this mapping and build a query in SQL or Transact-SQL (T-SQL) instead of building the (SELECT) statements manually? I'm currently on MS SQL Server 2019.
Please see this dbfiddle link for a full tables and example: https://dbfiddle.uk/Atku04Bo.
Share Improve this question edited Nov 21, 2024 at 19:07 Dale K 27.1k15 gold badges54 silver badges82 bronze badges asked Nov 21, 2024 at 16:29 DBoxDBox 711 silver badge7 bronze badges 4- Please read : Why should I provide a Minimal Reproducible Example, even for a very simple SQL query? – MatBailie Commented Nov 21, 2024 at 18:05
- @MatBailie I don't understand your comment, I gave a minimal reproducible example with the dbfiddle, I thought it was too much to put here. – DBox Commented Nov 21, 2024 at 20:27
- This looks like a terribly complicated design which will be very difficult for anyone else to maintain or amend. Why don't you describe the business problem you are trying to solve and design an appropriate normalised solution. This looks a bit like a one true lookup table type of design, if you haven't heard of that you should do a search for Phil Factor articles. red-gate.com/simple-talk/blogs/… – Steve Ford Commented Nov 21, 2024 at 22:15
- @SteveFord I couldn't agree more. This is a product someone uses and I'm trying to make sense of the backend DB for them. – DBox Commented Nov 21, 2024 at 22:50
1 Answer
Reset to default 1This can be done with dynamic SQL, using STRING_AGG
to concatenate the dynamic SELECT
statements.
DECLARE @sql NVARCHAR(MAX);
DECLARE @selectColumns NVARCHAR(MAX);
DECLARE @fromClause NVARCHAR(MAX);
SET @sql = '
SELECT a.ID AS A_ID, a.LINKID, b.ID AS B_ID, b.OTHER';
SET @fromClause = '
FROM TblA a
JOIN TblB b ON a.LINKID = b.LINKID;';
WITH LinkData AS (
SELECT
Key_Val,
Type,
DataType,
Length,
Description,
'TblSet' + CAST(Type AS VARCHAR(10)) +
CASE DataType
WHEN 1 THEN '_A'
WHEN 2 THEN '_B'
ELSE '_C' END AS TblSetTable,
CASE Type WHEN 1 THEN 'a.ID' ELSE 'b.ID' END AS IDColumn
FROM TblLink
)
SELECT @selectColumns = STRING_AGG(
'(SELECT [Value] FROM ' + TblSetTable + ' WHERE [ID] = ' + IDColumn + ' AND [Key_Val] = ' + CAST(Key_Val AS VARCHAR(10)) + ') AS [Item_' + CAST(Key_Val AS VARCHAR(10)) + ']',
', ')
FROM LinkData;
SET @sql = @sql + ', ' + @selectColumns + @fromClause;
EXEC sp_executesql @sql;
Output:
A_ID | LINKID | B_ID | OTHER | Item_2 | Item_3 | Item_4 | Item_5 | Item_7 | Item_8 | Item_9 | Item_10 | Item_15 | Item_16 | Item_17 | Item_18 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 100 | 1 | ID3 | 20 | null | Value 4 | 30 | null | null | null | null | Value 15 | null | null | null |
2 | 200 | 2 | ID4 | null | null | null | 45 | 50 | null | Value 9 | 60 | Value 15_2 | Value 16 | null | null |
2 | 200 | 3 | ID5 | null | null | null | 45 | null | null | Value 9 | 60 | null | null | null | null |
fiddle
本文标签: sqlCorrelate these tables dynamically (or automated)Stack Overflow
版权声明:本文标题:sql - Correlate these tables dynamically (or automated) - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736308924a1933832.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论