SQL Server中有工会的替代方案吗?

SQL Server中有工会的替代方案吗?,sql,sql-server,Sql,Sql Server,因此,我正在创建一个查询,它将返回我需要的所有数据 我的问题是: Declare @StartDate datetime Set @StartDate = '2/1/2018' Declare @EndDate datetime Set @EndDate = '4/5/2018' Declare @UserID int Set @UserId = '153056' ;with EntData as ( select distinct (Entity_ID), a.user_I

因此,我正在创建一个查询,它将返回我需要的所有数据

我的问题是:

Declare @StartDate datetime 
Set @StartDate = '2/1/2018'

Declare @EndDate datetime 
Set @EndDate = '4/5/2018'

Declare @UserID int
Set @UserId = '153056'

;with EntData as
(
select 
    distinct (Entity_ID), a.user_ID, c.User_OrganizationalUnitID 
from 
    ViewMgmt as a
    ViewConsole b on a.Role_ID = b.RoleID
    ViewUsers c on a.User_ID = c.UserID
where 
    b.RoleID in ( 53354666, 5363960) and 
    a.User_ID = @UserID  and
    a.Entity_ID <> 6912276036227
)

select a.User_ID, a.User_Name, a.UOName, 
    b.C_OID, c.OName,
    d.CID, e.Affected
from view.a
    inner join view_Cool.a1 on a.User_ID = a1.UserID and a.CI_D = a1.CID
    inner join view_New.b on a.CI_D = b.C_ID
    left join view_Large.c on b.C_OID = c.OID
    left join view_Small.d on a.CI_D = d.CID
    left join view_Old.e on d.Cert_ID = e.CI_D and a.User_ID = e.User_ID
    inner join EntData on b.C_OID = EntityData.Entity_ID
where ((a.ExpirationDate between @StartDate and @EndDate and a.ExpirationDate = a.ExpirationDate) 
    or (a.ExpirationDate between @StartDate and @EndDate and a.ExpirationDate is null)) and (a.UI <> 6912276036227 or a.UI <> 1414)
    and a1.IsHidden = 0 and a.UCS <> 13

UNION 

select a.User_ID, a.User_Name, a.UOName, 
    b.C_OID, c.OName,
    d.CID, e.Affected
from view.a
    inner join view_Cool.a1 on a.User_ID = a1.UserID and a.CI_D = a1.CID
    inner join view_New.b on a.CI_D = b.C_ID
    left join view_Large.c on b.C_OID = c.OID
    left join view_Small.d on a.CI_D = d.CID
    left join view_Old.e on d.Cert_ID = e.CI_D and a.User_ID = e.User_ID
    inner join EntData g on a.UI = g.OID
where ((a.ExpirationDate between @StartDate and @EndDate and a.ExpirationDate = a.ExpirationDate) 
    or (a.ExpirationDate between @StartDate and @EndDate and a.ExpirationDate is null)) and a.UI <> 6912276036227 
    and a.UI = 1414 
    and (c.OName like '%VXA%' or c.OName like '%Amazon%' or a.CI_D in (414,4561))
    and a1.Hidden = 0 and a.UCS <> 13
最初,联合的第一部分是我所有的,但是有人想看到一个ID a.UI=1414的额外数据。我不想为系统中的所有UI带回更多数据,所以我创建了一个联合,专门在一个UI中带回额外数据。我想要的数据回来了;但是,现在,不是在一分钟内加载,而是加载查询可能需要4分钟以上,而第一个SELECT语句则需要30-40秒。我已经和这个代码搏斗了一段时间了,我已经准备好让它高效地工作

我在想是否有办法在联合的最后一部分中,在a.UI=g.OID上执行最后一个连接内部连接EntData g,而不是只有在UI=1414时才必须附加一个完全独立的SELECT语句,但我认为这是不可能的。我尝试将最后一个连接实现到第一个SELECT中,但它没有运行。我还是SQL的新手,所以非常感谢您的帮助


谢谢。

您的共同问题几乎相同。尝试加入它们并从它们中进行一次查询。我认为这个查询应该返回相同的结果。但如果存在重复行,则将包含重复行

select a.User_ID, a.User_Name, a.UOName, 
    b.C_OID, c.OName,
    d.CID, e.Affected
from view.a
    inner join view_Cool.a1 on a.User_ID = a1.UserID and a.CI_D = a1.CID
    inner join view_New.b on a.CI_D = b.C_ID
    left join view_Large.c on b.C_OID = c.OID
    left join view_Small.d on a.CI_D = d.CID
    left join view_Old.e on d.Cert_ID = e.CI_D and a.User_ID = e.User_ID
    inner join EntData on b.C_OID = EntityData.Entity_ID
where ((a.ExpirationDate between @StartDate and @EndDate and a.ExpirationDate = a.ExpirationDate) 
    or (a.ExpirationDate between @StartDate and @EndDate and a.ExpirationDate is null)) and (a.UI <> 6912276036227)
    and a1.IsHidden = 0 and a.UCS <> 13

    and 1 = case 
                when a.UI = 1414 
                    case
                        when c.OName like '%VXA%' or c.OName like '%Amazon%' or a.CI_D in (414,4561) then 1
                        else 0 
                    end
                else 1
            end

我重构并添加了一些注释

DECLARE @StartDate datetime 
  SET @StartDate = '2018-02-01'  --- Use ISO 8601 dates. YYYY-MM-DD
DECLARE @EndDate datetime 
  SET @EndDate = '2018-04-05'  --- Use ISO 8601 dates. YYYY-MM-DD
DECLARE @UserID int
  SET @UserId = 153056  --- Remove single quotes. You're assigning a string to an int. 

; WITH EntData AS (
    SELECT DISTINCT Entity_ID , OID /* This needs to be included for later JOIN. Remove the other columns you don't use. */
    FROM ViewMgmt a  --- USE ANSI-92 syntax. Pretty please.
    INNER JOIN ViewConsole b on a.Role_ID = b.RoleID
        AND b.RoleID in ( 53354666, 5363960 )
    INNER JOIN ViewUsers c on a.User_ID = c.UserID
    WHERE  
        a.User_ID = @UserID  
        AND a.Entity_ID <> 6912276036227
)
, UnionedQueries AS ( -- Combine the common parts of the UNIONed queries into a second CTE for reuse.
    SELECT a.User_ID, a.User_Name, a.UOName
        , b.C_OID
        , c.OName
        , d.CID
        , e.Affected
        , a.UI  -- Added for UNION
        , a.CI_D -- Added for UNION
    FROM view.a a
    INNER JOIN view_Cool.a1 a2 ON a.User_ID = a1.UserID 
        AND a.CI_D = a1.CID
        AND a1.IsHidden = 0  --- Move this filter into the INNER JOIN. It will reduce the JOINed resultset.
    INNER JOIN view_New.b b ON a.CI_D = b.C_ID
        LEFT JOIN view_Large.c c ON b.C_OID = c.OID

    /* These JOINs are connecting across multiple tables. Make sure it's returning what you think it is how it should be. */
    LEFT JOIN view_Small.d d ON a.CI_D = d.CID 
    LEFT JOIN view_Old.e e ON d.Cert_ID = e.CI_D 
            AND a.User_ID = e.User_ID

    WHERE (
            ( a.ExpirationDate BETWEEN @StartDate AND @EndDate ) /* ??? and a.ExpirationDate = a.ExpirationDate ??? Typo? What was this supposed to do? */ 
            OR 
            ( a.ExpirationDate IS NULL ) --If this is checking for NULL, it won't be BETWEEN @StartDate and @EndDate
            --- These two conditions could be combined as ISNULL(a.ExpirationDate,@StartDate), but that is very micro-optimization.
        ) 
        and a.UI NOT IN ( 6912276036227, 1414 )  -- This is functionally the same as using two <>s, just easier to follow.
        and a.UCS <> 13
)
/* Now that the common query is already run, we can just use those results to get our final UNION */
SELECT u1.User_ID, u1.User_Name, u1.UOName, u1.C_OID, u1.OName, u1.CID, u1.Affected
FROM UnionedQueries u1
INNER JOIN EntData ON u1.C_OID = EntData.Entity_ID  -- This JOIN seems to be the only significant difference between the two queries.

UNION

SELECT u2.User_ID, u2.User_Name, u2.UOName, u2.C_OID, u2.OName, u2.CID, u2.Affected
FROM UnionedQueries u2
INNER JOIN EntData g on u2.UI = g.OID -- This JOIN seems to be the only significant difference between the two queries.
WHERE u2.UI = 1414 
    AND ( 
        u2.OName LIKE '%VXA%' 
        OR u2.OName LIKE '%Amazon%' 
        OR u2.CI_D IN ( 414,4561 )
    )
;

注:这需要进行测试。我不知道EntData CTE过滤了多少查询数据,因此将其排除在外可能会导致主查询中的数据集更大

样本数据和期望的结果真的会有帮助。为什么你们需要联合呢?从第一个查询中删除它和`or a.UI 1414`。如果没有重复,结果将是相同的rows@uzi考虑到OP使用的是UNION,而不是UNION ALL,那么就不会出现重复项。UNION在UNION都没有的地方删除重复项,因此通常更快;特别是如果重复项不重要,并且以另一种方式避免了它。@Larnu,我注意到了重复项,不管怎样,where子句中的条件似乎是相同的,但我错过了一个。所以我之前的评论是wrong@GordonLinoff在不发布实际数据的情况下,我如何做到这一点?谢谢。这无疑加快了查询速度,但我仍然缺少包含c.OName(如“%VXA%”或c.OName(如“%Amazon%”)的数据,这与两个Select语句中的最终联接有关。我需要'EntData on b.C_OID=EntityData.Entity_ID',但当UI=1414时需要'Internal join EntData g on a.UI=g.OID'。有什么方法可以为联接添加条件吗?4144561中类似于“%VXA%”的条件c.OName或类似于“%Amazon%”的条件c.OName或a.CI\u D仅应用于a.UI=1414。不是吗?