我正在尝试构建一个驱动视图的查询。我正在寻找的功能似乎经常出现,我很确定他们是一个更好的替代品,而不是使用像我一直在做的CASE子查询。
假设我们有两个带有主键的表,就像这样。让我们说,对于这个例子,表b有一个约束条件,每个年级只能分配一名教师,但任何数量的教师都可以被分配到一个年级。
table a
gradeid grade
-------------------
1 A
2 B
3 C
4 D
5 F
table b
teachid gradeid teacher
-------------------------
1 1 mary
2 1 bob
3 2 sue
4 3 sally
5 4 sally
6 5 rich
7 1 bill
8 2 bill
9 3 chris
现在假设我们要编写一个视图查询,用于某些导出到excel功能,从表a中获取数据并将其连接到表b,以便我们可以看到特定等级是否存在正连接每次匹配不返回多行,并且必须手动压平数据。我们想要的是一个被表A的结果数量锁定的视图(在这个示例中为5,但我们可以添加更多等级并让它向下扩展)以下是我们的视图:
注的休息意味着不鲍勃或billaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
所有其他独特的老师比赛
View
gradeid grade bobsname bobsid billsname billsid restids restnames
-------------------------------------------------------------------
1 A bob 2 bill 7 1 mary
2 B null null bill 8 3 sue
3 C null null null null 4,9 sally,chris
4 D null null null null 5 sally
5 F null null null null 6 rich
我可以这样做的方法是使用带有CASE语句的子查询。
像
这样的东西
SELECT a.gradeid, a.grade,
CASE WHEN (select bob.teachid from tableb bob left join on a.gradeid = bob.gradeid) IS NOT NULL (select bob.teachid from tableb bob left join on a.gradeid = bob.gradeid) ELSE NULL END as bobsid,
CASE WHEN (select bob.teacher from tableb bob left join on a.gradeid = bob.gradeid) IS NOT NULL (select bob.teacher from tableb bob left join on a.gradeid = bob.gradeid) ELSE NULL END as bobsname,
CASE WHEN (select bill.teachid from tableb bill left join on a.gradeid = bill.gradeid) IS NOT NULL (select bill.teachid from tableb bill left join on a.gradeid = bill.gradeid) ELSE NULL END as billsid,
CASE WHEN (select bill.teacher from tableb bill left join on a.gradeid = bill.gradeid) IS NOT NULL (select bill.teacher from tableb bill left join on a.gradeid = bill.gradeid) ELSE NULL END as billsname,
CASE WHEN REALLY LONG THING THAT IS TOO UGLY TO WRITE AND MAKES ME ASK HERE ETC....
FROM table a
这可能是实现这一目标的唯一方法,但我相信必须有更好的方法来实现这一目标。有什么建议吗?
答案 0 :(得分:1)
不确定bob和bill以及“rest”是否显着。如果是这样,这会给你你想要的东西
;with bob as
(
select gradeid, teacher as bobsname, teachid as bobsid
from #tab2
where teacher = 'bob'
),
bill as
(
select gradeid, teacher as billsname, teachid as billsid
from #tab2
where teacher = 'bill'
),
rest as
(
select gradeid,
substring(cast(ids.ids as varchar(8000)), 2, 7999) as restids,
substring(cast(names.names as varchar(8000)), 2, 7999) as restnames
from
(
select distinct gradeid
from #TAB2
) t1
cross apply
(
select ',' + convert(varchar, teachid)
from #tab2 t2
where t1.gradeid = t2.gradeid
and teacher not in ('bob','bill')
order by teachid
for xml path('')
) ids(ids)
cross apply
(
select ',' + teacher
from #tab2 t2
where t1.gradeid = t2.gradeid
and teacher not in ('bob','bill')
order by teachid
for xml path('')
) names(names)
)
select grade, max(bobsname), max(bobsid), max(billsname), max(billsid), max(restnames), max(restids)
from #tab1
inner join #tab2 on #TAB1.gradeid = #tab2.gradeid
left outer join bob on #tab2.teachid = bobsid and bob.gradeid = #TAB1.gradeid
left outer join bill on #tab2.teachid = billsid and bill.gradeid = #TAB1.gradeid
left outer join rest on rest.gradeid = #TAB1.gradeid
group by grade
答案 1 :(得分:0)
然后你需要使用动态编码。
问题中的架构
CREATE TABLE #TAB1(gradeid INT, grade VARCHAR(20))
INSERT INTO #TAB1
SELECT 1,'A'
UNION ALL
SELECT 2,'B'
UNION ALL
SELECT 3,'C'
UNION ALL
SELECT 4,'D'
UNION ALL
SELECT 5,'F'
CREATE TABLE #TAB2(teachid INT,gradeid INT, teacher VARCHAR(20))
INSERT INTO #TAB2
SELECT 1 , 1 , 'mary'
UNION ALL
SELECT 2 , 1 , 'bob'
UNION ALL
SELECT 3 , 2 , 'sue'
UNION ALL
SELECT 4 , 3, 'sally'
UNION ALL
SELECT 5 , 4 , 'sally'
UNION ALL
SELECT 6 , 5 , 'rich'
UNION ALL
SELECT 7 , 1 , 'bill'
UNION ALL
SELECT 8 , 2 , 'bill'
UNION ALL
SELECT 9 , 3 , 'chris'
现在通过构建动态查询来查询表
DECLARE @QRY VARCHAR(MAX), @TEACHERNAMES VARCHAR(MAX)='', @TEACHERIDS VARCHAR(MAX)=''
,@ALIASES VARCHAR(MAX)=''
--Names column for PIVOTing Name wise
SELECT @TEACHERNAMES= @TEACHERNAMES+'[' + teacher + '],' FROM
(SELECT DISTINCT teacher FROM #TAB2)A
SELECT @TEACHERNAMES = SUBSTRING(@TEACHERNAMES,1,LEN(@TEACHERNAMES)-1)
--ID column names for PIVOTing ID wise
SELECT @TEACHERIDS= @TEACHERIDS+'[' + teachid + '],' FROM
(SELECT DISTINCT CAST(teachid AS VARCHAR(20))teachid FROM #TAB2)A
SELECT @TEACHERIDS = SUBSTRING(@TEACHERIDS,1,LEN(@TEACHERIDS)-1)
--Aliases as your requirement
SELECT @ALIASES =@ALIASES
+ '['+CAST(TEACHID AS VARCHAR(20))+'] AS '+TEACHER+'_id ,['+teacher+'] AS '+teacher+'_name'+','
FROM #TAB2
SELECT @ALIASES = SUBSTRING(@ALIASES,1,LEN(@ALIASES)-1)
SELECT @QRY = '
SELECT T1.GRADEID, '+@ALIASES+' FROM #TAB1 T1
LEFT JOIN (
SELECT * FROM (
SELECT * FROM #TAB2
)AS A
PIVOT
(
MAX(teachid) FOR teacher IN ('+@TEACHERNAMES+')
) AS PVT
)ID
ON T1.gradeid= ID.GRADEID
LEFT JOIN
(
SELECT * FROM (
SELECT * FROM #TAB2
)AS A
PIVOT
(
MAX(teacher) FOR teachid IN ('+@TEACHERIDS+')
) AS PVT
)AS NAME
ON T1.gradeid= NAME.gradeid
'
EXEC( @QRY)