联合查询效率

时间:2014-07-18 13:45:41

标签: sql sql-server union nested-queries

我正在根据两个独有条件从表中检索所有记录。每个记录都是重复的,其中重复记录具有单独的标志isWaitList = 1,并且父存储其子节点的主ID存储在字段waitListProdID中;子记录在其waitListProdID字段中将为0,因为它们不能拥有自己的子级(即子元素只有一级深度)。

表格的相关行为conferenceID (int), [description] (varchar), maxAttendance (int), currentAttendance (int), isWaitlist (bit), waitListProdID (int)

条件是:

  1. 如果currentAttendance<
  2. 检索父/子。 maxAttendance(通用)
  3. 如果其父行满足currentAttendance> = maxAttendance
  4. ,则仅检索子项

    这个联盟可以解决这个问题,不过我想知道A)我是否已经足够有效地编写了它,并且B)如果这可以更好地作为单个(如果更复杂的)查询?

    SELECT conferenceID, [description]
    FROM tblEventConferences
    WHERE currentAttendance < maxAttendance
    AND isWaitList = 0
    AND eventID = 624
    
    UNION
    
    SELECT conferenceID, [description]
    FROM tblEventConferences
    WHERE isWaitlist = 1
    AND currentAttendance < maxAttendance
    AND conferenceID NOT IN (
          SELECT waitlistProdID
          FROM tblEventConferences
          WHERE isWaitList = 0
          AND eventID = 624
          AND currentAttendance < maxAttendance
    )
    

2 个答案:

答案 0 :(得分:2)

尝试使用CTE定义核心逻辑(eventID和考勤计数)。

然后将所有内容包装到一个查询中,以确保不再存在重复的删除成本。

个人偏好,但我使用NOT EXISTS而不是NOT INS,请参阅此处出于某些原因:What's the difference between NOT EXISTS vs. NOT IN vs. LEFT JOIN WHERE IS NULL?

代码:

;with cte as (
    SELECT conferenceID, waitlistProdID, [description], isWaitlist, currentAttendance, maxAttendance
    FROM tblEventConferences
    WHERE currentAttendance < maxAttendance
    AND eventID = 624
)
select c.conferenceID, c.[description]
from cte c
where c.isWaitlist = 1
or (c.isWaitList = 0 and not exists (
      select top 1 1
      from cte ne
      where ne.waitlistProdID = c.conferenceID
))

修改

只需阅读提及该查询与意图不符的评论。即父母/子女的出勤比较不同。

如果是这种情况,则需要进行以下调整:

;with cte as (
    SELECT conferenceID, waitlistProdID, [description], isWaitlist, currentAttendance, maxAttendance
    FROM tblEventConferences
    WHERE eventID = 624
)
select c.conferenceID, c.[description]
from cte c
where (c.isWaitlist = 1 and c.currentAttendance < c.maxAttendance)
or (c.isWaitList = 0 and not exists (
    select top 1 1
    from cte ne
    where ne.waitlistProdID = c.conferenceID
    and ne.currentAttendance >= ne.maxAttendance
))

答案 1 :(得分:0)

UNION在删除重复文件时会产生开销。我认为一个查询会比一个联盟更好:

SELECT conferenceID, [description]
FROM tblEventConferences
WHERE currentAttendance < maxAttendance AND
      ((isWaitList = 0 AND eventID = 624) OR
       (isWaitlist = 1 AND
        conferenceID NOT IN (SELECT waitlistProdID
                             FROM tblEventConferences
                             WHERE isWaitList = 0 AND eventID = 624 AND
                                   currentAttendance < maxAttendance
                            )
       )
      );

一个缺点是SQL Server可能更容易优化每个子查询。所以这值得一试,但不能保证。