来自行的连接列值
我正在使用SQL Server 2000后端的时间表系统,我需要列出他们旁边的导师和房间的事件,这可能会超过1个,因此可以将多行房间和导师转换为+分隔列表。我用下面的代码在过去:来自行的连接列值
DECLARE @Tutors as varchar(8000)
SELECT @Tutors = isnull(@Tutors + ' + ', '') + name
FROM (
SELECT CT_EVENT_STAFF.event_id, CT_EVENT_STAFF.weeks,
CT_STAFF.unique_name, CT_STAFF.name
FROM celcat200809.dbo.CT_EVENT_STAFF AS CT_EVENT_STAFF
LEFT OUTER JOIN celcat200809.dbo.CT_STAFF AS CT_STAFF
ON CT_EVENT_STAFF.staff_id = CT_STAFF.staff_id
WHERE event_id = @eventID
) As data_set
print @Tutors
的事项标识是唯一的事件,这只会工作的时候我知道确切的ID,我不能为每一个ID运行它。
有没有办法做到这一点,每个单独的event_id没有游标。不幸的是,我的第二个问题是时间表系统(CELCAT)为每年创建一个新的数据库(我知道不问),所以我将不得不使SQL动态化明年的数据库将是celcat200910,我相信动态SQL不能在UDF中运行。
请记住这是SQL Server 2000中
您仍然可以使用goodgai建议的视图,但不是让它重定向到一个表,而是让它联合选择表。如果尚未完成并且您需要它,可以将年/月分成列。
CREATE VIEW UNIFIED_CT_STAFF
AS
SELECT year = 2008, month = 9, unique_name, name FROM celcat200809.dbo.CT_STAFF
UNION SELECT year = 2008, month = 10, unique_name, name FROM celcat200810.dbo.CT_STAFF
您可以创建一个UDF来计算的字符串,然后使用它像:
if object_id('dbo.GetTutorText') is not null
drop function dbo.GetTutorText
go
create function dbo.GetTutorText(
@eventID int)
returns varchar(8000)
as
begin
DECLARE @Tutors as varchar(8000)
SELECT @Tutors = isnull(@Tutors + ' + ', '') + name
FROM (
SELECT CT_EVENT_STAFF.event_id, CT_EVENT_STAFF.weeks,
CT_STAFF.unique_name, CT_STAFF.name
FROM celcat200809.dbo.CT_EVENT_STAFF AS CT_EVENT_STAFF
LEFT OUTER JOIN celcat200809.dbo.CT_STAFF AS CT_STAFF
ON CT_EVENT_STAFF.staff_id = CT_STAFF.staff_id
WHERE event_id = @eventID
) As data_set
return @Tutors
end
go
:
select event_id, dbo.GetTutorsText(@eventId)
from EventsTable
的UDF可以像定义
returns varchar(4000) DECLARE @Tutors as varchar(8000) tsk。啧。 也isnull(@Tutors +'+','') - > @Tutors +'+'永远为空 – Coentje 2009-06-29 16:00:44
对于第二个问题,使用VIEW。为celcat数据库中的每个感兴趣的表创建一个视图,然后使用视图。
当数据库进展到下一年时,只需更新所有视图以指向新的数据库。系统中使用VIEW的每个查询都将处理正确的数据库。
我可以问一下你为什么需要连接在服务器上的名字?客户端应用程序不能为你做这件事吗?
如果您在其他数据库中寻址表时遇到问题,请使用标准化名称创建视图(每个表一个),只需从每个表中选择*即可。您可以编写一个自动创建视图的SP,让您只传入要设置所有视图的数据库的名称。这些观点不会以任何重大的方式损害业绩。
由于您正在使用CT_STAFF的左连接,因此我相信职员可能会丢失,在这种情况下,您的表达式会将数据连接起来而丢失数据,因为它不允许NULL员工名称(它会在每次遇到NULL职员名称时重置列表)。
这里有可能就是你所需要的查询,但它是一个黑客位的:
SELECT
seqid = identity(int, 1, 1),
event_id,
S.name
INTO #EventNames
FROM
celcat200809.dbo.CT_EVENT_STAFF ES
LEFT JOIN celcat200809.dbo.CT_STAFF S ON ES.staff_id = S.staff_id
ORDER BY
event_id,
S.name --optional, whatever you like here.
SELECT
EN.event_id,
Max(CASE seqid - minseqid WHEN 0 THEN EN.name ELSE '' END))
+ Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 1 THEN EN.name ELSE NULL END, ''))
+ Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 2 THEN EN.name ELSE NULL END, ''))
+ Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 3 THEN EN.name ELSE NULL END, ''))
+ Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 4 THEN EN.name ELSE NULL END, ''))
+ Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 5 THEN EN.name ELSE NULL END, ''))
+ Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 6 THEN EN.name ELSE NULL END, ''))
+ Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 7 THEN EN.name ELSE NULL END, ''))
+ Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 8 THEN EN.name ELSE NULL END, ''))
+ Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 9 THEN EN.name ELSE NULL END, ''))
+ Max(Coalesce(' + ' + CASE seqid - minseqid WHEN 10 THEN EN.name ELSE NULL END, ''))
FROM
#EventNames EN
INNER JOIN (
SELECT event_id, minseqid = Min(seqid) FROM #EventNames GROUP BY event_id
) X ON EN.event_id = X.event_id
GROUP BY EN.event_id
只要确保把那些最大的就够了()的表达式中覆盖最大每个活动可能有多少员工。
要获取有关该事件的更多数据,请勿将其放入临时表(这会让它变慢)。只要使用这个大的查询作为它自己的派生表,并回到你需要的表。
在过去的几个月中,我已经做了一些celcat开发 - 这有点噩梦,我很同情你!老实说,在这种情况下,你可能会更好地使用Celcat API(这需要一些习惯,但功能相当强大,并且具有这样的优点,即你的查询应该在各个版本中相当安全)。
我创建了一个类,我用它来选择特定的数据库版本等,创建特定于我想要使用的学年的会话。
在API中,如果需要,还可以选择直接运行SQL。
我知道这并不回答你的问题,但我希望它能解决你的问题!
关于DB的安排:听起来很粗糙。是的,UDF中不允许动态SQL。你可能会发现一些有用的帮助,在这个线程的多个数据库工作:http://stackoverflow.com/questions/1037174/sql-use-statement-with-variable/1037961#1037961 ...但是,我认为最好的解决方案会试图找到某种方式将数据放在某个数据库中 - 但这可能超出了您的权限和责任范围。 – 2009-06-25 15:45:47
我将大部分数据放入考勤数据和类似数据的独立数据库中。我使用隔夜过程来填充这些东西,但是这个特定查询需要生效 – PeteT 2009-06-26 00:52:39