Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2006.07.23;
Скачать: [xml.tar.bz2];

Вниз

union по двум SP   Найти похожие ветки 

 
Ega23 ©   (2006-05-17 10:09) [0]

Всем привет!
MS SQL 2000

Есть SP, возвращает некий набор данных.
Надо вызвать её 2 раза (с разными параметрами) и полученные 2 набора данных "запихать" в один и передать на клиент.
В принципе, есть такой вариант - создаём временную таблицу с полями, как в SP, делаем в неё 2 раза insert из exec"а, на клиент передаём Select * from #tempTable.
Вариант не нравится тем, что набор данных, возвращаемый SP, ещё не устаканился - возможно будут добавлены некоторые поля или изменены существующие.
В двух местах это делать не хочется.

Собственно, вопрос: описаный мной вариант - наиболее приемлимый, или есть всё-таки что-то получше?


 
Sergey13 ©   (2006-05-17 10:14) [1]

Если двойной результат будет нужен часто, то почему бы не переделать саму SP?


 
ЮЮ ©   (2006-05-17 10:25) [2]

Предпочитаю в таких случаях UDF. Это же круто:

 SELECT * FROM function(1)
 UNION
 SELECT * FROM function(2)

SELECT * FROM
  function(2) f
  JOIN Table t ON ...


 
Ega23 ©   (2006-05-17 10:37) [3]


> Если двойной результат будет нужен часто, то почему бы не
> переделать саму SP?


Хм... 2 параметра сразу... А логику "внутре" реализовать...
Ты знаешь, пожалуй так и сделаю...


 
Polevi ©   (2006-05-18 09:16) [4]

OPENROWSET


 
Ega23 ©   (2006-05-18 09:28) [5]


> OPENROWSET


А не долго будет?


 
Desdechado ©   (2006-05-18 11:39) [6]

А почему бы просто не объединить через UNION ALL ?
без всяких UDF


 
ЮЮ ©   (2006-05-18 11:53) [7]


> Desdechado ©   (18.05.06 11:39) [6]
А почему бы просто не объединить через UNION ALL ?
без всяких UDF


знаеешь как? Скажи. Об этом и спрашивают: как объединить НД, возвращаемые ХП с двумя разнвми параметрами.


 
Desdechado ©   (2006-05-18 12:25) [8]

а чем принципиально отличается
SELECT f1, f2 FROM t1 WHERE f3=:P1
UNION ALL
SELECT f1, f2 FROM t1 WHERE f4=:P2

от
SELECT f1, f2 FROM proc1(:P1)
UNION ALL
SELECT f1, f2 FROM proc1(:P2)


 
Ega23 ©   (2006-05-18 12:53) [9]


> А почему бы просто не объединить через UNION ALL ?


Потому, что в MS SQL, к сожалению, нельзя обращаться к ХП так, как к View.
Более того, если ХП, к примеру, возвращает НД из пяти столбцов, а мне для результирующей выборки нужно всего 3, то приходится создавать временную таблицу из пяти столбцов, имеющих типы данных и идущих в таком порядке, в каком возвращает их ХП, заливать данные из ХП в эту временную таблицу и уже из неё делать финальный select по трём столбцам.


 
Ega23 ©   (2006-05-18 12:55) [10]


> SELECT f1, f2 FROM proc1(:P1)
> UNION ALL
> SELECT f1, f2 FROM proc1(:P2)


Приведи пример. Конкретный. В синтаксисе TSQL. Для MS SQL 2000.
Сумеешь - при личной встрече ящик пива выставлю.


 
Desdechado ©   (2006-05-18 12:56) [11]

Ega23 ©   (18.05.06 12:53) [9]
кошмар какой
даже IB умеет это делать, не говоря уж об оракле


 
Desdechado ©   (2006-05-18 12:59) [12]

Ega23 ©   (18.05.06 12:55) [10]
> Приведи пример Для MS SQL 2000
увы, MSSQL не владею, но всегда считал, что синтаксис там достаточно развитый
видимо, ошибался
а может, все-таки есть скрытые резервы?

> при личной встрече
сомневаюсь, что она состоится в обозримом будущем
слишком далеко


 
Ega23 ©   (2006-05-18 13:03) [13]


> даже IB умеет это делать, не говоря уж об оракле


Увы. В MSSQL такое, к сожалению, невозможно. М.б. в 2005 и ввели, но его я ещё не "ковырял". Собственно, я ветку поэтому и организовал...


> сомневаюсь, что она состоится в обозримом будущем


Всяко бывает. Мир тесен.


 
ЮЮ ©   (2006-05-18 13:18) [14]

А чем он не конкретный? proc1 - UDF, возвращающая DataSet

CREATE FUNCTION dbo.UeNotActualDepartments(
 @OnDate datetime, @Document int = -1, @ExcludeDocument int = 0
)
RETURNS @Res TABLE(Department int)
-- Функция возвращает коды всех детей в дереве подразделений
AS
BEGIN
 INSERT INTO @Res
         SELECT od.Department
         FROM
           E_OldDepartments od
           JOIN E_DepartmentChanges dc ON od.DepartmentChange = dc.Id
           LEFT JOIN E_DepartmentDocuments dd ON dc.DepartmentDocument = dd.Id
           LEFT JOIN E_Documents doc ON dd.Document = doc.Id
           LEFT JOIN E_NewDepartments ren ON
             (od.Department = ren.Department) and
             (od.DepartmentChange = ren.DepartmentChange)
           WHERE
             (
               (doc.Id IS NULL) OR
               (dd.DateFrom <= @OnDate) AND (
                 (@ExcludeDocument = 1) AND (doc.Id <> @Document) AND
                 (doc.ApplicationType = 1)
                 OR
                 (@ExcludeDocument = 0) AND
                 ((doc.ApplicationType = 1) OR (doc.Id = @Document))
               )
             ) AND
             (ren.ID IS NULL)
order by od.Department
 RETURN
END


Не лучший вариант, как оказалось, делать INSERT INTO @Res при значительных объемах. В приведеннов варианте он вообще лишний, т.к. все выбирается одним запросом и для этого имеется другой синтаксис UDF (смотри ниже). Но иногда, когда требуется много действий, курсор фетчить, то эта конструкция само то.

В следущей процедуре потребовались некоторые константы, так сказать на уровне бизнесс логики, поэтому применил эту же крнструкцию. Но в результате выбор из UDF  сьал в 2 раза длинее, чем сам запрос, в ней выполнявшийся. Поэтому я поступил так: константы сделал параметрами, а над этой UDF обернул другую с аргументами-константами. вызов вложенных функций по времени оказался как и простое выполнение запроса. Итак


 
ЮЮ ©   (2006-05-18 13:21) [15]

CREATE FUNCTION dbo._UsTheoryLoad_LoadWorkPlansInfo(
@Year int, @Department int, @FactorVariant int,
@IndependentStudyHoursSubActivity int, @IndependentStudyControl int,
@CurrentConsulting int, @BeforeExamConsulting int
)
RETURNS TABLE
AS
RETURN (
 SELECT
   ISNULL(dg.ID, sg.ID) UGroup,
   f.ID Factor,
   wlhc.WorkLine,
   wlhc.SubActivity,
   wlhc.Hours,
   wlhc.Control,
   ISNULL( wpfs.ID, wpfc.ID) WorkPlanFactor,
   CASE
     WHEN MirrorWorkTermActivity = ExistWorkTermActivity
     THEN wl.StartDay
     ELSE wta.StartDay
   END StartDate,
   CASE
     WHEN MirrorWorkTermActivity = ExistWorkTermActivity
     THEN wl.Weeks
     ELSE wta.Weeks

   END Weeks,
   wt.WorkPlan,
   sta.Activity,
   (a.Course + wp.Year - a.Year) Course,
   ISNULL(ISNULL(wl.NAME, sd.Name), std.Name) Name ,
   sh.WeekHours,
   sh.StudyDiscipline,
   sd.StudyPlan,
   sd.StandardDiscipline,
   sd.MasterLine,
   std.StandardPlan,
   std.Cycle,
   std.Component,
   pf.ID ParentFactor,
   wl.Department,
   f.Name FactorName,
   fac.CODE Budget,
   fac.Short_Name FacultyName,
   fac.Short_Name + " " +
     ISNULL(szql.CODE + "-" + sz.CODE, ql.CODE) + " " +
     ISNULL(
       szs.ShortName + " (" +
         CASE
           WHEN RIGHT(szql.CODE, 2) = "65"
           then ""
           ELSE " (" + szql.ShortName + "); "
         END +
         sz.ShortName + ")",
      ISNULL(s.ShortName, s.Name) +
         CASE
           WHEN RIGHT(ql.CODE, 2) = "65" then "" ELSE " (" + ql.ShortName + ")"
         END
   ) SpecialityName,
   ISNULL(wl.RoomHoursAreCalculated, sp.RoomHoursAreCalculated)
     RoomHoursAreCalculated,
   sp.StudyForm,
   ISNULL(ISNULL(wl.NAME, sd.Name), std.Name) +
     CASE
       WHEN Cycle = 5
       THEN "(Факультатив)"
       ELSE
         CASE WHEN Component = 3 THEN "(Выбор)" ELSE "" END
     END DisciplineName,
   fvv.FactorValue FactorValue,
   pfvv.FactorValue ParentFactorValue,
   fvv.ForPeopleQuantity,
   fvv.ForTimePeriod,
   fpq.Name ForPeopleQuantityName,
   ftp.Name ForTimePeriodName,
   sg.ID StudyGroup,
   sg.Name GroupName,
   dbo.UuCount_UGroups_Budget(ISNULL(dg.ID, sg.ID)) BudgetCnt,
   dbo.UuCount_UGroups_Pay(ISNULL(dg.ID, sg.ID)) PayCnt,
   NULL SGroup
 FROM
   dbo.UsTheoryLoad_GetWorkTermActivities (@Year) tlwta
   LEFT JOIN (SELECT * FROM U_WorkLines wl Where Department = @Department) wl
     ON tlwta.ExistWorkTermActivity = wl.WorkTermActivity
   LEFT JOIN (
     SELECT
       WorkLine, SubActivity, Hours, NULL Control FROM U_WorkHours
     UNION
     SELECT
         WorkLine, SubActivity, wl.CurrentHours - wlh.Hours * wl.Weeks Hours,Control
     FROM
       (
         SELECT
           wh.WorkLine, @IndependentStudyHoursSubActivity SubActivity,
           Sum(wh.Hours) Hours, NULL Control
         FROM
           U_WorkHours wh
           LEFT JOIN U_WorkLines wl ON wh.WorkLine = wl.ID
         WHERE
           (wl.Department = @Department) and
           (Subactivity < 4) and (
             (wl.RoomHoursAreCalculated IS NULL) OR
             (wl.RoomHoursAreCalculated = 0)
           )
         GROUP By WorkLine
         HAVING Sum(Hours) > 0
       ) wlh
       LEFT JOIN U_WorkLines wl ON wlh.WorkLine = wl.ID
     WHERE wl.CurrentHours - wlh.Hours * wl.Weeks > 0    
     UNION
     SELECT  WorkLine, NULL, Quantity, Control FROM U_WorkControls
   ) wlhc ON wlhc.WorkLine = wl.ID

+++++++++++++++++++++в форум столько не лезет +++++++++++++

   LEFT JOIN S_FactorValues pfvv ON
     (pfvv.ID = ISNULL (pfvdn.ID, ISNULL(pfvd.ID, pfv.ID)))
      AND (pfvv.FactorVariant = @FactorVariant) AND (pfvv.FactorValue > 0)
   JOIN U_Groups sg ON (wt.WorkPlan = sg.WorkPlan)
   LEFT JOIN U_Groups dg ON
     (dg.UGroup = sg.ID) AND (sh.StudyDiscipline = dg.StudyDiscipline)

WHERE
 (sa.ID IS NOT NULL) OR  (c.ID IS NOT NULL) OR (f.ID = @IndependentStudyControl)
)


 
ЮЮ ©   (2006-05-18 13:21) [16]

функция-обертка:


CREATE FUNCTION dbo.UsTheoryLoad_LoadWorkPlansInfo(
@Year int, @Department int, @FactorVariant int
)
RETURNS TABLE
AS
RETURN (
 SELECT *
 FROM dbo._UsTheoryLoad_LoadWorkPlansInfo(
   @Year, @Department, @FactorVariant, 10023, 85, 2, 11
 )
)


Ну и использование:

Declare @Year int
Declare @Department int
Declare @FactorVariant int

set @Year = 2006
set @Department = 16 -- каф АЯ
set @FactorVariant = 2

Select * FROM dbo.UsTheoryLoad_LoadWorkPlansInfo(@Year, @Department, @FactorVariant)
UNION
Select * FROM dbo.UsTheoryLoad_LoadWorkPlansInfo(2005, @Department, @FactorVariant)


или


Select * FROM
 dbo.UsTheoryLoad_LoadWorkPlansInfo(@Year, @Department, @FactorVariant)n
 FULL JOIN dbo.UsTheoryLoad_LoadWorkPlansInfo(2005, @Department, @FactorVariant)o
ON (o.UGroup = n.UGroup) AND (o.Factor = n.Factor) and (o.WorkLine = n.WorkLine)
WHERE
(o.UGroup IS NULL) OR (n.UGroup IS NULL)


 
ЮЮ ©   (2006-05-18 13:27) [17]

Ну вот, пока примеры подыскивал и постил, за моим пивом уже пришли :)


 
Ega23 ©   (2006-05-18 13:38) [18]

UDF не дадут делать...  :-(

Да и не такой уж жуткий запрос получается, сделал через #TempTable.
Но за идею - спасибо, на досуге обдумаю...


 
ЮЮ ©   (2006-05-19 02:59) [19]

>UDF не дадут делать...  :-(

а SP дают. Станно. Это же объекты практически одного плана, только одни PROCEDURE, а вторые - FUNCTION.


 
Ega23 ©   (2006-05-19 09:59) [20]


> а SP дают. Станно. Это же объекты практически одного плана,
>  только одни PROCEDURE, а вторые - FUNCTION.


Должна оставаться совместимость с 7.0, а там функций нет.


 
Desdechado ©   (2006-05-19 11:29) [21]

если честно, когда говорят "ХП", то у меня даже не возникает вопроса - функция это или процедура
для меня это одно и то же (наверно, от IB осталось :)
поэтому и недоумение было


 
Ega23 ©   (2006-05-19 11:34) [22]

На самом деле у меня к TSQL достаточно много претензий, особенно после того, как я FB "пощупал".



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2006.07.23;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.019 c
2-1151815487
Sco
2006-07-02 08:44
2006.07.23
Меню на раб столе


2-1151932710
greenbegin
2006-07-03 17:18
2006.07.23
конвертация текста DOS - Win


15-1150783795
Ega23
2006-06-20 10:09
2006.07.23
С Днём рождения! 20 июня


6-1142345239
Skazi
2006-03-14 17:07
2006.07.23
Печать и IntraWeb


2-1151875430
susergey
2006-07-03 01:23
2006.07.23
Запомнить путь к папке





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский