需要SQL逻辑可能需要子查询

时间:2016-07-05 20:05:52

标签: sql sql-server

我正在构建一个查询,我需要检索MEMBERS表中的所有记录,其中连接日期(datejoin)介于两个日期之间,某个成员资格类型(mtypeid)之一,以及特定位置(siteid) )。

然后,我需要从SCSCHEDULER(此表存储所有约会)表中撤回所有行,其中这些成员的约会在某个特定日期之后安排,具有某种类型的约会且仍处于活动状态

我有以下内容,但我相信我需要将一些逻辑放在子查询中,因为我只返回有约会成员的数据。我需要至少为没有任何约会的成员以及那些有约会的成员和scscheduler数据从会员表中返回数据。

SELECT        MEMBERS.scancode, MEMBERS.lname, MEMBERS.fname, MEMBERTYPES.description, MEMBERS.status, MEMBERS.datejoin, EMPLOYEES.lname AS Expr1, 
                         EMPLOYEES.fname AS Expr2, SCSCHEDULES.scheduledatefrom, SCSCHEDULES.timeduration, SCSCHEDULES.scheduledescription, 
                         SCSCHEDULES.schedulestatus
FROM            MEMBERS LEFT OUTER JOIN
                         SCSCHEDULES ON MEMBERS.memid = SCSCHEDULES.memid INNER JOIN
                         MEMBERTYPES ON MEMBERS.mtypeid = MEMBERTYPES.mtypeid INNER JOIN
                         EMPLOYEES ON MEMBERS.employeeid = EMPLOYEES.employeeid
WHERE        (MEMBERS.datejoin BETWEEN @rvStartDate AND @rvEndDate) AND (MEMBERS.siteid = '779') AND (MEMBERS.mtypeid = '1' OR
                         MEMBERS.mtypeid = '10' OR
                         MEMBERS.mtypeid = '12' OR
                         MEMBERS.mtypeid = '28' OR
                         MEMBERS.mtypeid = '32' OR
                         MEMBERS.mtypeid = '33' OR
                         MEMBERS.mtypeid = '34' OR
                         MEMBERS.mtypeid = '35' OR
                         MEMBERS.mtypeid = '36' OR
                         MEMBERS.mtypeid = '40' OR
                         MEMBERS.mtypeid = '48') AND (SCSCHEDULES.scheduledatefrom >= @rvStartDate) AND (SCSCHEDULES.scheduledescription = 'First' OR
                         SCSCHEDULES.scheduledescription = 'Second') AND (SCSCHEDULES.schedulestatus = '1')

2 个答案:

答案 0 :(得分:1)

当您尝试过滤SCSCHEDULES子句中的WHERE时(在外部联接之后),您最终会丢弃要保留的行。它们需要放在连接条件中或包含在派生表中,如下所示:

SELECT m.scancode, m.lname, m.fname, mt.description, m.status, m.datejoin,
       e.lname AS Expr1, e.fname AS Expr2,
       s.scheduledatefrom, s.timeduration, s.scheduledescription, s.schedulestatus
FROM   MEMBERS AS m
       LEFT OUTER JOIN
       (
       SELECT * FROM SCSCHEDULES
       WHERE
               scheduledatefrom >= @rvStartDate
           AND scheduledescription IN ('First', 'Second')
           AND schedulestatus = '1'
       ) AS s
           ON m.memid = s.memid
       INNER JOIN MEMBERTYPES AS mt
           ON m.mtypeid = mt.mtypeid
       INNER JOIN EMPLOYEES AS e
           ON m.employeeid = e.employeeid
WHERE      m.datejoin BETWEEN @rvStartDate AND @rvEndDate
       AND m.siteid = '779'
       AND m.mtypeid IN (
           '1', '10', '12', '28', '32', '33', '34', '35', '36', '40, '48'
       );

答案 1 :(得分:1)

LEFT JOIN中,除第一个表外的所有条件都应该放在ON子句而不是WHERE子句中:

SELECT m.scancode, m.lname, m.fname, mt.description, m.status, m.datejoin,
       e.lname AS Expr1, e.fname AS Expr2,
       s.scheduledatefrom, s.timeduration, s.scheduledescription, s.schedulestatus
FROM MEMBERS m LEFT OUTER JOIN
     SCSCHEDULES s
     ON MEMBERS.memid = s.memid AND scheduledatefrom >= @rvStartDate AND
        scheduledescription IN ('First', 'Second') AND
        schedulestatus = '1' INNER JOIN
     MEMBERTYPES mt
     ON m.mtypeid = mt.mtypeid INNER JOIN
     EMPLOYEES e
     ON m.employeeid = e.employeeid
WHERE m.datejoin BETWEEN @rvStartDate AND @rvEndDate AND
      m.siteid = '779' AND
      m.mtypeid IN ('1', '10', '12', '28', '32', '33', '34', '35', '36', '40, '48');

注意:如果您的ID是数字,那么您应该删除单引号。混合类型可能会使优化器混淆。

另请注意,表别名使查询更易于编写和阅读。