SQL:从用户

时间:2016-05-02 20:50:01

标签: sql sql-server tsql

我正在尝试根据从用户收到的表列表构建动态查询。 我在下面有几个尝试过的解决方案。 我认为CTE是要走的路,但我很难弄清楚如何实现它。 我真的很感激天才能让我知道如何做到这一点!

这些是表格: W,WD,WE,WSF,WSFE,XDF,XDFE,Y,YD,Z,ZD

这些是每组表加入的列:

  

W,Y,WD,WE,WSF

     
    

WID

  
     

WSF,WSFE,XDF

     
    

WSFID

  
     

XDF,XDFE

     
    

XDFID

  
     

Y,YD,Z

     
    

YID

  
     

Z,ZD

     
    

ZID

  

如果用户选择W,Y,Z,则构建此查询(然后可以由exec或sp_executesql执行):     select * from #W w join yY on y.WID = w.WID join zZ on z.YID = y.YID

declare @Fields table (
ID int identity not NULL,
Name varchar(200)
)

declare @Tables table (
ID int identity not NULL,
Field varchar(200),
TempTable varchar(200)
)

declare @QueryTables table (
ID int identity not NULL,
[Table] varchar(200),
Alias varchar(20)
)

declare @QueryJoins table (
ID int identity not NULL,
Table1 varchar(20),
Col1 varchar(200),
Table2 varchar(20),
Col2 varchar(200)
)

insert @Fields
values
('W'),
('Y'),
('Z')

insert @Tables
values
('W', '#W'),
('WD', '#WD'),
('WE', '#WE'),
('WSF', '#WSF'),
('WSFE', '#WSFE'),
('XDF', '#XDF'),
('XDFE', '#XDFE'),
('Y', '#Y'),
('YD', '#YD'),
('Z', '#Z'),
('ZD', '#ZD')

insert @QueryTables
values
('#W', 'w'),
('#WD', 'wd'),
('#WE', 'we'),
('#WSF', 'wsf'),
('#WSFE', 'wsfe'),
('#XDF', 'xdf'),
('#XDFE', 'xdfe'),
('#Y', 'y'),
('#YD', 'yd'),
('#Z', 'z'),
('#ZD', 'zd')

insert @QueryJoins
values
('w', 'WID', 'wd', 'WID'),
('w', 'WID', 'we', 'WID'),
('w', 'WID', 'wsf', 'WID'),
('w', 'WID', 'xdf', 'WID'),
('w', 'WID', 'y', 'WID'),
('wd', 'WID', 'w', 'WID'),
('we', 'WID', 'wd', 'WID'),
('wsf', 'WID', 'wd', 'WID'),
('wsf', 'WSFID', 'wsfe', 'WSFID'),
('wsfe', 'WSFID', 'wsf', 'WSFID'),
('wsf', 'WSFID', 'xdf', 'WSFID'),
('xdf', 'WID', 'w', 'WID'),
('xdf', 'WSFID', 'wsf', 'WSFID'),
('xdf', 'XDFID', 'xdfe', 'XDFID'),
('xdfe', 'XDFID', 'xdf', 'XDFID'),
('y', 'WID', 'w', 'WID'),
('y', 'YID', 'yd', 'YID'),
('yd', 'YID', 'y', 'YID'),
('y', 'YID', 'z', 'YID'),
('z', 'YID', 'y', 'YID'),
('z', 'ZID', 'zd', 'ZID'),
('zd', 'ZID', 'z', 'ZID')

--attempted solution number 1:
select
*
from @Fields vf
join @Tables vt
on vt.Field = vf.Name
join @QueryTables vqt
on vqt.[Table] = vt.TempTable
join @QueryJoins vqj
on vqj.Table1 = vqt.Alias
join @QueryTables vqt2
on vqt2.Alias = vqj.Table2
join @Tables vt2
on vt2.TempTable = vqt2.[Table]
join @Fields vf2
on vf2.Name = vt2.Field

--attempted solution number 2:
;with cte (FieldID, [Table], Table1, Col1, Table2, Col2, I) as (
select
    vf.ID as FieldID,
    vqt.[Table],
    vqj.Table1,
    vqj.Col1,
    vqj.Table2,
    vqj.Col2,
    1
from @Fields vf
join @Tables vt
    on vt.Field = vf.Name
join @QueryTables vqt
    on vqt.[Table] = vt.TempTable
join @QueryJoins vqj
    on vqj.Table1 = vqt.Alias
union all
select
    vf.ID as FieldID,
    vqt.[Table],
    vqj.Table1,
    vqj.Col1,
    vqj.Table2,
    vqj.Col2,
    I + 1
from @Fields vf
join @Tables vt
    on vt.Field = vf.Name
join @QueryTables vqt
    on vqt.[Table] = vt.TempTable
join @QueryJoins vqj
    on vqj.Table1 = vqt.Alias
join cte cte
    on cte.Table1 = vqj.Table2
        and cte.Table2 = vqj.Table1
where I <= FieldID --a feeble attempt to control the recursion
)
select * from cte

1 个答案:

答案 0 :(得分:0)

一个有趣的问题,绝对是数据建模代码的味道(如果Z,Y和YD都有YID列,听起来你需要一个桥表或类似的结构来管理那里的关系。或者如果Z和YD很小查找,只需加入它们,让优化器处理开销。)

注意:我在名称&lt;上创建了字段自连接名称,所以你只需要Table1&lt;中的QueryJoins数据。表2。这会将你的QueryJoins表减少一半,但你也错过了一些“正确的”连接(即你有我们/ wd而不是wd /我们)

{{1}}