SELECT INTO在子查询中

时间:2011-02-03 15:33:45

标签: sql sql-server-2005 tsql correlated-subquery

环境:SQL Server 2005

我有这种类型的请求

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个子查询。查看请求。我想要:

  • 所有活跃用户,具有高级或中级访问权限以及谁是经理
  • 这些用户的所有服务
  • 这些用户的所有访问权限

5 个答案:

答案 0 :(得分: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

根据原始问题的扩展进行更新

两个子查询的解决方案与一个子查询的解决方案基本相同,只是不返回两个结果集,而是返回三个。和以前一样,每个子查询都使用临时表/变量:

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

答案 1 :(得分:1)

您可以将子查询拉出来制作临时表,然后从临时表中执行您想要的两个查询。

答案 2 :(得分: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

答案 3 :(得分: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

答案 4 :(得分:-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'