2009-06-25 5 views
0

Я использую систему расписания с бэкэнд 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 

event_id является уникальным событием, это будет работать только тогда, когда я знаю точно ID, я не могу запустить его для каждого ID.

Есть ли способ сделать это для каждого отдельного event_id без курсоров. Я видел возможное решение этого при использовании UDF, к сожалению, моя вторая проблема заключается в том, что система расписания (CELCAT) создает новую базу данных для каждого года (я знаю, что не спрашиваю), поэтому мне придется сделать динамику SQL, т. Е. следующая база данных будет celcat200910, я считаю, что динамический SQL не может быть запущен в UDF.

Пожалуйста, помните, что это SQL Server 2000

+0

На устройствах БД: звучит грубо. Да, динамический SQL в UDF не разрешен. Вы можете найти полезную помощь в этом потоке для работы с несколькими БД: http://stackoverflow.com/questions/1037174/sql-use-statement-with-variable/1037961#1037961 ... однако, я думаю, что наилучшим решением было бы попытайтесь найти способ разместить данные в одной БД где-нибудь - но это может быть выше и выше вашей цели/вызова долга. –

+0

Я помещаю большую часть данных в отдельную базу данных для данных посещаемости и т.п. Я использую ночную процедуру для заполнения этого материала, однако этот конкретный запрос должен быть активным – PeteT

ответ

1

Вы все еще можете использовать представление в качестве предложения 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 
0

Вы можете создать UDF для расчета строки, а затем использовать его как:

select event_id, dbo.GetTutorsText(@eventId) 
from EventsTable 

ОДС может быть определен как:

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 
+0

возвращает varchar (4000) DECLARE @Tutors as varchar (8000) tsk. яй. также isnull (@Tutors + '+', '') -> @Tutors + '+' никогда не является нулевым – Coentje

+0

Исправлен тип возврата, но второе предложение неверно: @Tutors будет null для первой найденной строки , – Andomar

0

Для вашей второй проблемы используйте VIEW. Создайте представление для каждой таблицы, представляющей интерес в базе данных celcat, и вместо этого используйте представления.

Когда база данных прогрессирует до следующего года, просто обновите все представления, чтобы указать на новую базу данных. Каждый запрос в системе, использующий VIEW, теперь будет обращаться к правильной базе данных.

+0

Я знаю, что вы говорите, но обычно запросы на самом деле используют несколько лет базы данных. Я работаю в колледже и celcat, а также в расписании есть посещаемость студентов, это сравнивается между партиями. – PeteT

0
  • Могу ли я спросить, почему вы должны объединить имена на сервере? Не может ли клиентское приложение сделать это за вас?

  • Если у вас возникли проблемы с обращением к таблицам в других базах данных, создайте представления со стандартизованными именами, по одному на таблицу, которые просто выбирают * из каждой таблицы. Вы можете написать SP, который автоматически создает представления, позволяя вам передать только имя базы данных, для которой вы хотите установить все представления. Представления не будут наносить ущерб производительности каким-либо значительным образом.

  • Поскольку вы используете левое соединение с CT_STAFF, это заставляет меня поверить, что персонал может отсутствовать, и в этом случае вы потеряете данные своим выражением, которое объединяет их, поскольку оно не позволяет сотрудникам NULL name (это приведет к сбросу списка каждый раз, когда встречается имя 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 

Просто убедитесь в том, достаточно тех, Макс() выражения для покрытия величайшая возможное количество сотрудников на каждое мероприятие.

Чтобы получить больше данных о мероприятии, не помещайте его в таблицу темпа (это сделает его медленнее).Просто используйте этот большой запрос как свою собственную производную таблицу и присоединитесь к таблицам, которые вам нужны.

0

За последние несколько месяцев я немного развил celcat - это немного кошмар, и я сочувствую вам!

Чтобы быть честным, в этой ситуации вам, вероятно, будет лучше использовать Celcat API (который немного привыкает, но достаточно мощный и имеет то преимущество, что ваши запросы должны быть достаточно безопасными для версий.)

Я создал класс, который я использовал для выбора конкретных версий базы данных и т. Д., Создавая сеанс, определенный для учебного года, который я хотел использовать.

Внутри API есть возможность напрямую запускать SQL, если вам нужно.

Я знаю, что это не отвечает на ваш вопрос, но я надеюсь, что он решает вашу проблему!