2011-02-03 2 views
2

Окружающая среда: SQL Server 2005SELECT INTO внутри подзапроса

У меня есть этот тип запроса

SELECT * 
FROM user 
WHERE EXISTS(
    SELECT * 
    FROM user_access 
    WHERE user_access.user_id = user.user_id 
    AND user_access.access IN ('HIGH_LEVEL','MEDIUM_LEVEL') 
) 
AND EXISTS(
SELECT * 
FROM user_service 
WHERE user_service.role ='Manager' 
AND user.id_user = user_service.user_id 
) 
AND user.is_active ='True' 

Но в результате я бы также хотел бы получить результат от подзапроса, так что я хотя о чем-то вроде

DECLARE @user_access TABLE(user_id int,access nvarchar(30)) 
DECLARE @user_service TABLE(user_id int,service_id int,role nvarchar(10)) 
SELECT * FROM user 
    WHERE EXISTS(
     SELECT user_id,access INTO [@user_access] 
     FROM user_access 
     WHERE user_access.user_id = user.user_id 
     AND user_access.access IN ('HIGH_LEVEL','MEDIUM_LEVEL') 
    ) 
AND EXISTS(
SELECT user_id , service_id,role INTO @user_service 
FROM user_service 
WHERE user_service.role ='Manager' 
AND user.id_user = user_service.user_id 
) 
    AND user.is_active ='True' 


SELECT * FROM @user_acess 
select * from @user_service 

Но я получаю следующее сообщение об ошибке:

"Неверный синтаксис рядом с ключевым словом" INTO "."

У вас есть идеи, как я могу это сделать, не делая дважды подзапрос (я пробовал с временной таблицей, той же ошибкой)?

РЕДАКТИРОВАТЬ: Извините за моего товарища, который пытался решить мою проблему, я забыл одно: у меня есть два подзапроса. См. Запросы. Я хочу:

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

ответ

2

Временная таблица или переменная выглядят как простейшее решение. Поместите результаты подзапроса в временную таблицу или переменную, а затем выполните два оператора select в конце вашей процедуры.

Declare @UserAccesses Table (
          user_id ... 
          , access varchar(...) 
          ) 

Insert @UserAccesses(user_id, access) 
Select UA.user_id, UA.access 
From user_access As UA 
    Join user As U 
     On U.user_id = UA.user_Id 
Where U.is_active = 'True' 
    And UA.access In('HIGH_LEVEL', 'MEDIUM_LEVEL') 

Select ... 
From user 
Where Exists (
       Select 1 
       From @UserAccess As UA1 
       Where UA1.user_id = user.user_id 
       ) 

Select user_id, access 
From @UserAccesses 

Update дали свое расширение первоначального вопроса

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

Declare @UserAccesses Table (
          user_id int 
          , access nvarchar(30) 
          ) 

Declare @UserServices Table (
          user_id int 
          , service_id int 
          , role nvarchar(10) 
          ) 

Insert @UserAccesses(user_id, access) 
Select UA.user_id, UA.access 
From user_access As UA 
    Join user As U 
     On U.user_id = UA.user_Id 
Where U.is_active = 'True' 
    And UA.access In('HIGH_LEVEL', 'MEDIUM_LEVEL') 

Insert @UserServices(user_id, service_id, role) 
Select user_id , service_id,role 
From user_service 
Where user_service.role ='Manager' 
    And Exists (
       Select 1 
       From @UserAccesses As UA1 
       Where UA1.user_id = user_service.user_id 
       ) 

Select ... 
From user 
Where Exists (
       Select 1 
       From @UserServices As US1 
       Where US1.user_id = user.user_id 
       ) 

Select user_id, access 
From @UserAccesses As UA 
Where Exists (
        Select 1 
        From @UserServices As US1 
        Where US1.user_id = UA.user_id 
        ) 

Select user_id, access 
From @UserServices 
+0

факт в том, что ваш ответ кажется правильным (вот почему я его поддержал). Но я не задал свой вопрос хорошо, потому что у меня есть 2 подзапроса (это проблема с упрощением вашего бизнеса для вопроса). Смотрите мои правки –

+0

@remi bourgarel - Учитывая, что вы пересмотрели, я расширил свой ответ. Ответ на два подзапроса аналогичен ответу одного подзапроса. – Thomas

1

Вы можно вытащить подзапрос, чтобы создать временную таблицу, а затем выполнить два запроса, которые вы хотите получить из таблицы temp.

+0

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

+0

Ум, конечно. Потяните временную таблицу. Затем вы можете запускать любые запросы, которые вы хотите, с любыми фильтрами, которые вы хотите. Вы можете выполнить 20 запросов с разными фильтрами, если у вас есть временная таблица. –

-1

Это должно возвращать набор результатов из обеих таблиц.

SELECT * 
FROM user u, user_access a 
WHERE u.user_id in (
    SELECT user_access.user_id 
    FROM user_access 
    WHERE user_access.user_id = u.user_id 
    AND user_access.access IN ('HIGH_LEVEL','MEDIUM_LEVEL') 
    AND user_access.user_id = u.user_id 
) 
AND a.user_id = u.user_id 
AND u.is_active ='True' 
+0

Плохое решение для меня: я получу все свои записи от пользователя один раз для каждой записи, которая есть в user_access, поэтому, если у одного пользователя есть 2 доступа, я получу дважды один и тот же id => Мне не нравится в два раза больше той же информации, это заставляет меня делать некоторые странные логики отображения в моем коде приложения. –

+1

-1 для использования неявного синтаксиса – HLGEM

1

Речь идет о лучшем, что вы можете сделать для оптимизации. Невозможно захватить и сохранить данные в подзапросах EXISTS - , особенно, когда EXISTS не полностью оценивает набор результатов. Это короткие замыкания, когда в подзапросе найдено совпадение SINGLE (один пользователь access), поэтому вы все равно не можете получить все записи access.

declare @user table (user_id int) 
insert @user 
SELECT [user].user_id 
FROM [user] 
WHERE EXISTS(
    SELECT * 
    FROM user_access 
    WHERE user_access.user_id = [user].user_id 
    AND user_access.access IN ('HIGH_LEVEL','MEDIUM_LEVEL') 
    ) 
AND EXISTS(
    SELECT * 
    FROM user_service 
    WHERE user_service.role ='Manager' 
    AND [user].id_user = user_service.user_id 
    ) 
AND [user].is_active ='True' 

SELECT [user].* FROM [user] inner join @user u on u.USER_ID = [user].user_id 
SELECT a.user_id, a.access FROM user_access a inner join @user u on u.USER_ID = a.user_id 
SELECT s.user_id, s.service_id, s.role FROM user_service s inner join @user u on u.USER_ID = s.user_id 
+0

+1 Beat me to it –

+0

@cyberwiki: ваше решение может быть хорошим, но вы пропустите фильтр по двум последним запросам: «user_access.access IN (« HIGH_LEVEL »,« MEDIUM_LEVEL ») » и «user_service.role = ' Manager '" –

+0

@remi - Мое предположение заключалось в том, что это были фильтры для пользователей. После того, как вы сделали это для пользователей, я предположил, что вы хотите получить все их доступ и роли. Если это не так, это так же просто, как добавить фильтры к последним 2. – RichardTheKiwi

0

Вот реализация того, что Ken Down^ предложил, и я думаю, что его результат не должен содержать каких-либо посторонних строк, принимая во внимание то, что вы после этого.

DECLARE @user_access TABLE(user_id int,access nvarchar(30)) 
DECLARE @user_service TABLE(user_id int,service_id int,role nvarchar(10)) 

INSERT INTO @user_access 
SELECT ua.user_id, ua.access 
FROM user_access ua 
    INNER JOIN [user] u ON ua.user_id = u.user_id 
WHERE u.is_active ='True' 
    AND ua.access IN ('HIGH_LEVEL','MEDIUM_LEVEL') 

INSERT INTO @user_service 
SELECT us.user_id , us.service_id, us.role 
FROM user_service us 
    INNER JOIN [user] u ON us.user_id = u.user_id 
WHERE u.is_active ='True' 
    AND us.role ='Manager' 


SELECT u.* 
FROM [user] u 
    INNER JOIN (
    SELECT user_id FROM @user_access 
    UNION 
    SELECT user_id FROM @user_service 
) uas ON uas.user_id = u.user_id 
SELECT * FROM @user_acess 
SELECT * FROM @user_service 
+0

SI здесь, вы запрашиваете 3 раза в таблице пользователей, противоположное решение не лучшее, но лучше: сначала выберите пользователя, а затем выберите другую необходимую вам информацию. И когда вы не используете данные из таблицы для своего набора результатов, используйте существующий (или, если хотите) не JOIN, здесь ваш JOIN с пользователем бесполезен и плох для производительности. –

+0

Я не видел в вашем вопросе, что таблица 'user' должна быть затронута не более одного раза (или дважды). Что касается 'сначала выберите пользователя, а затем выберите другую необходимую информацию' - ну, другая информация * подготовлена ​​* до выбора пользователей, но выбирает из этих таблиц после выбора из' user'. Во всяком случае, у моего решения была ошибка: он мог отображать повторяющиеся строки из 'user'. И это исправлено сейчас. –