将同一张表的行值与特定条件进行比较

时间:2019-09-06 08:34:39

标签: sql-server join nested-loops

数据库的屏幕截图: enter image description here

我想通过比较非admin(is_admin = true)用户的用户名与admin用户的用户名来在SQL中显示数据。我只想显示anno_type,capture_end,capture_start和严重性与admins值不匹配的数据。例如如果非管理员具有从1(capture_start)到3401(capture_end)的noisy(anno_type)且noise(severity)(严重性)的某些数据,但是管理员已将其标记为nois(最小值从1到3401),将noisy(中度从3401改为6401),则查询应该显示从3401到6401的中等噪声

自从我处理了如此复杂的(对我而言)sql查询以来已有7年了。我只记得一点点的SQL。 我记得加入,但不知道如何在这里申请

我在此代码上取得了一些成功:

SELECT *
FROM test
WHERE capture_end IN
    (SELECT capture_end
     FROM test
     WHERE username = 'P' AND drive_session_name = '046_156')
  AND capture_start IN
    (SELECT capture_start
     FROM test
     WHERE username = 'P' AND drive_session_name = '046_156')
  AND anno_type NOT IN
    (SELECT anno_type
     FROM test
     WHERE username = 'P' AND drive_session_name = '046_156')
  AND severity IN
    (SELECT severity
     FROM test
     WHERE username = 'P' AND drive_session_name = '046_156')
  AND drive_session_name = '046_156'
  AND username != 'P'

如果管理员和非管理员使用相同批注的严重性不同,则不会显示数据

1 个答案:

答案 0 :(得分:0)

您可以EXIST获得相同的结果。 EXISTS是半联接,可以为索引正确的表提供良好的性能。

在这里,我使用了cte来避免使用多个内部选择语句

;WITH cte AS (
    SELECT capture_end,anno_type,severity
    FROM test
    WHERE username = 'P' AND drive_session_name = '046_156'
)
SELECT *
FROM test t
WHERE drive_session_name = '046_156' AND username != 'P'
AND EXISTS (SELECT 1 FROM CTE WHERE CTE.capture_end = t.capture_end)
AND EXISTS (SELECT 1 FROM CTE WHERE CTE.anno_type = t.anno_type)
AND EXISTS (SELECT 1 FROM CTE WHERE CTE.severity = t.severity)

编辑:上面的代码只是您编写的代码的一种更好的方法。

自问过

  

我只想显示数据,其中anno_type,capture_end,   capture_start和严重性与管理员值不符

您可以尝试一些简单的EXCEPT

示例:

select capture_start,capture_end,anno_type,severity
from test
where is_admin = 'true' -- <addtional where conditions>
except 
select capture_start,capture_end,anno_type,severity
from test
where is_admin = 'false'  -- <addtional where conditions>

将为管理员用户提供所有不匹配的条目。反转表,您可以更改非管理员用户的权限。

我用最少的数据here创建了一个小提琴