#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:
Я вижу два решения:
- используйте табличные функции вместо процедур (доступно с SQL Server 2005)
или
- используйте временную таблицу, используя табличную переменную (ОБЪЯВИТЕ @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. глобальные временные таблицы создают условие гонки. Не используйте их, если вы не абсолютно уверены, что каждый из них будет использоваться не более чем одним процессом.