Вы возвращаете массив и помещаете его в имеющийся массив $ test, поэтому он стал многомерным массивом. Вы можете изменить имя функции, но просто сделайте это:
$test = [];
getTest($test, 'test_key');
function getTest(&$array,$key){
$array[$key] = 'test_value';
}
UDF является черным квадратом к оптимизатору запросов, таким образом, он выполняется для каждой строки. Вы делаете курсор строки строкой. Для каждой строки в активе ищите идентификатор три раза в другой таблице. Это происходит, когда Вы используете скаляр, или составной UDFs (Встройте UDFs, просто макросы, которые расширяются во внешний запрос),
Одна из многих статей о проблеме является "Скалярными функциями, встраиванием и производительностью: интересный заголовок для скучного сообщения".
Подзапросы могут быть оптимизированы, чтобы коррелировать и избежать операций строки строкой.
То, что Вы действительно хотите, является этим:
SELECT
uc.id AS creator,
uu.id AS updater,
uo.id AS owner,
a.[name]
FROM
asset a
JOIN
user uc ON uc.user_pk = a.created_by
JOIN
user uu ON uu.user_pk = a.updated_by
JOIN
user uo ON uo.user_pk = a.owned_by
Февраль 2019 обновления
SQL Server 2019 начинает решать эту проблему.
Как другие плакаты предположили, использование соединений определенно даст Вам лучшую общую производительность.
Однако, так как Вы заявили, что это не хотите головную боль поддержания подобных соединений с 50 выходами или подзапросов, попытка использовать встроенную табличную функцию следующим образом:
CREATE FUNCTION dbo.get_user_inline (@user_pk INT)
RETURNS TABLE AS
RETURN
(
SELECT TOP 1 id
FROM ice.dbo.[user]
WHERE user_pk = @user_pk
-- AND active = 1
)
Ваш исходный запрос затем стал бы чем-то как:
SELECT
(SELECT TOP 1 id FROM dbo.get_user_inline(created_by)) AS creator,
(SELECT TOP 1 id FROM dbo.get_user_inline(updated_by)) AS updater,
(SELECT TOP 1 id FROM dbo.get_user_inline(owned_by)) AS owner,
[name]
FROM asset
Встроенная табличная функция должна иметь лучшую производительность или, чем скалярная функция или, чем составная табличная функция.
Производительность должна быть примерно эквивалентна Вашему исходному запросу, но любые будущие изменения могут быть внесены в UDF, делая его намного более удобным в сопровождении.
Получить тот же результат (ПУСТОЙ УКАЗАТЕЛЬ, если пользователь удален или не активный).
select
u1.id as creator,
u2.id as updater,
u3.id as owner,
[a.name]
FROM asset a
LEFT JOIN user u1 ON (u1.user_pk = a.created_by AND u1.active=1)
LEFT JOIN user u2 ON (u2.user_pk = a.created_by AND u2.active=1)
LEFT JOIN user u3 ON (u3.user_pk = a.created_by AND u3.active=1)
Я пропускаю что-то? Почему это не может работать? Вы только выбираете идентификатор, который Вы уже имеете в таблице:
select created_by as creator, updated_by as updater,
owned_by as owner, [name]
from asset
Между прочим, в разработке Вас действительно должен избежать ключевых слов, как name
, как имена полей.