изменение хранимой процедуры для включения результатов из другой хранимой процедуры / запроса

#sql #tsql

#sql #tsql

Вопрос:

У меня есть эта хранимая процедура, которая возвращает список сведений о клиентах с учетом параметров

 PROCEDURE [dbo].[vExport_GetClientDetailsBySchemeAndTeam]
            @startdate DATETIME = null,
            @enddate DATETIME = NULL,
            @scheme INT,
            @teamID INT
 AS
/*returns a  list of current client details between two dates */


SELECT 
    Forename,
    Surname,
    Address1,
    Address2,
    Town,
    County,
    Postcode,
    [Status],
    Telephone,
    EmergencyTelephone
    --exec vExport_GetClientDetailsBySchemeAndTeam '2010-04-06 12:00:00', '2011-04-06 12:00:00', '3', '152'
FROM
    vClients
WHERE
    vClients.ClientID in
        (SELECT DISTINCT
            E.ClientID 
            FROM vEvents E
            INNER JOIN vClients C on E.ClientID = C.ClientID
            WHERE E.EventDate between @startdate and @enddate
            --AND C.Status = 0
            AND e.SchemeID=@scheme
            AND e.TeamID = @teamID)
  

Однако теперь мне нужно включить в select (last eventdate) результат другого SP. который по сути выглядит следующим образом:

 SELECT TOP 1 * from vEvents  E where E.ClientID =  @ClientID
order by e.EventDate desc
  

Как я могу вернуть эту дату последнего события для всех клиентов в первом операторе select, используя второй запрос?

Застрял!!

Ответ №1:

 PROCEDURE [dbo].[vExport_GetClientDetailsBySchemeAndTeam]
            @startdate DATETIME = null,
            @enddate DATETIME = NULL,
            @scheme INT,
            @teamID INT
 AS
/*returns a  list of current client details between two dates */


SELECT 
    Forename,
    Surname,
    Address1,
    Address2,
    Town,
    County,
    Postcode,
    [Status],
    Telephone,
    EmergencyTelephone,
    (SELECT top 1 e.EventDate from vEvents  E where E.ClientID =  vClients.ClientID order by e.EventDate desc)
    --exec vExport_GetClientDetailsBySchemeAndTeam '2010-04-06 12:00:00', '2011-04-06 12:00:00', '3', '152'
FROM
    vClients
WHERE
    vClients.ClientID in
        (SELECT DISTINCT
            E.ClientID 
            FROM vEvents E
            INNER JOIN vClients C on E.ClientID = C.ClientID
            WHERE E.EventDate between @startdate and @enddate
            --AND C.Status = 0
            AND e.SchemeID=@scheme
            AND e.TeamID = @teamID)
  

Комментарии:

1. Это не «включить в выборку результат другого SP», это «включить в выборку тот же запрос другого SP». Я понимаю, что результат подходит для Oded, тем не менее, это не одно и то же.

2. @Skrol29 amun1000 специально не просил использовать SP в запросе. amun1000 просто хотел включить результат (дату последнего события) SP, запрос которого был задан. Я бы сделал это по-другому, если бы нужно было использовать SP.

3. @Eric.K.Yung: если это так, то вопрос тривиален и совершенно бесполезен. Копирование кода для того, чтобы он работал в другом месте, является тривиальной и часто плохой практикой.

4. @Skrol29 это может быть правдой, что ответ бесполезен для многих людей. Однако для amun1000 это достаточно хорошо — минимальный код для выполнения работы. Я использовал код автора, чтобы помочь ему получить ответ, который он хотел. Я считаю, что именно так можно лучше учиться, когда кто-то вносит простые изменения. Я не собираюсь использовать код для себя.

5. Вы можете дополнительно оптимизировать свой запрос, заменив подзапрос в WHERE ... IN... производной таблицей, которая включает только самую последнюю дату события в заданном диапазоне дат

Ответ №2:

Это твой друг:

 create table #sp_output
(
  col_1 ... ,
  ...
  col_n ... ,
)

INSERT #sp_output EXECUTE <your-stored-procedure-of-choice>
  

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

Ответ №3:

Сведите это к объединению с производной таблицей:

 SELECT 
    Forename,
    Surname,
    Address1,
    Address2,
    Town,
    County,
    Postcode,
    [Status],
    Telephone,
    EmergencyTelephone,
    E.MostRecentEventDate
FROM
    vClients C INNER JOIN (
        SELECT
            ClientID,
            MAX(EventDate) AS [MostRecentEventDate]
        FROM vEvents
        WHERE EventDate BETWEEN @startdate AND @enddate
            AND SchemeID=@scheme
            AND TeamID = @teamID
        GROUP BY ClientID
    ) E ON C.ClientID = E.ClientID
  

Использование временной таблицы для чего-то такого простого было бы ненужным и привело бы к полной трате ресурсов базы данных.

Ответ №4:

Я вижу два решения:

  1. используйте табличные функции вместо процедур (доступно с SQL Server 2005)

    или

  2. используйте временную таблицу, используя табличную переменную (ОБЪЯВИТЕ @temp TABLE (…)), которая имеет ту же структуру, что и результат другой хранимой процедуры. Затем используйте инструкцию INSERT EXECUTE, чтобы сохранить результат другой хранимой процедуры во временной таблице.
    ВСТАВЬТЕ @temp ВЫПОЛНИТЕ OtherStoredProc
    , после чего вы получите результат другой хранимой процедуры в таблице @temp

Ответ №5:

Буквальный ответ на ваш вопрос заключается в создании глобальной временной таблицы и пошаговом заполнении этой таблицы.

Например:

     PROCEDURE [dbo].[vExport_GetClientDetailsBySchemeAndTeam] @startdate DATETIME = null, @enddate DATETIME = NULL, @scheme INT, @teamID INT AS /*returns a list of current client details between two dates */
    create table ##results(//columns you want to return)
insert into ##results (columns)

    SELECT Forename, Surname, Address1, Address2, Town, County, Postcode, [Status], Telephone, EmergencyTelephone --exec vExport_GetClientDetailsBySchemeAndTeam '2010-04-06 12:00:00', '2011-04-06 12:00:00', '3', '152' FROM vClients WHERE vClients.ClientID in (SELECT DISTINCT E.ClientID FROM vEvents E INNER JOIN vClients C on E.ClientID = C.ClientID WHERE E.EventDate between @startdate and @enddate --AND C.Status = 0 AND e.SchemeID=@scheme AND e.TeamID = @teamID)

update results
set (columns from you events table)
from ##results r, 
vEvents e
where e.clientid = r.clientid

select * from ##results
  

Однако, я думаю, вы также можете достичь желаемого с помощью традиционного объединения. Стоит посмотреть, можете ли вы присоединиться к таблице событий из вашего основного запроса…

Комментарии:

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