【问题标题】:Converting ANSI operators in SQL在 SQL 中转换 ANSI 运算符
【发布时间】:2016-11-25 22:53:54
【问题描述】:

在将以下 2 个查询转换为 ANSI 兼容代码时需要帮助。我的代码使用 =* 运算符,我需要将它们转换为右外连接。我已经给了它一个很好的尝试,但是,无法获得预期的结果。

查询 1

SELECT m.MatterID, m.MatterType,
    m.HasSuppressionOrder, m.Complexity, 
    m.DateReceived, m.DateCompleted,
    ph.OfficerID, pe.Surname + ', ' + pe.GivenNames, h1.Result
FROM   CMS.MATTER m,
    CMS.PHASE ph,
    CMS.PERSON pe,
    CMS.HEARING h1
WHERE             
    (m.DateCompleted BETWEEN '2015-10-29 00:00:00' and '2015-10-30 00:00:00') 
    AND (ph.MatterID = m.MatterID 
    and ph.PhaseSeq = (SELECT MAX(ph2.PhaseSeq) FROM CMS.PHASE ph2 where ph2.MatterID = m.MatterID)) 
    AND (pe.PersonNo = (SELECT mp.PersonNo FROM CMS.MATTER_PERSON mp
            WHERE mp.MatterID = m.MatterID and mp.MatterPersonType = 'DEF')) 
    AND (h1.MatterID =* m.MatterID and --NON ANSI JOIN OPERATORS THAT NEED CONVERSION
    h1.PhaseSeq =* ph.PhaseSeq and --NON ANSI JOIN OPERATORS THAT NEED CONVERSION
    h1.HearingDateTime =* (SELECT MAX(h2.HearingDateTime)FROM CMS.HEARING h2 WHERE h2.MatterID = m.MatterID))
ORDER BY m.MatterID

查询 2

SELECT  m.MatterID,
    m.MatterType,
    m.HasSuppressionOrder,
    m.DateReceived,
    ISNULL (ph.OfficerID, 'No Phase'),
    ISNULL (pe.Surname, 'No Accused Registered') + ', ' + pe.GivenNames,
    m.Complexity,
    m.ProgramCode,
    m.Comments,
    m.StaffGroup,
    m.StaffSubGroup
FROM   CMS.MATTER m,
    CMS.PHASE ph, 
    CMS.PERSON pe
WHERE m.DateReceived BETWEEN '2015-09-30 00:00:00' AND '2015-10-30 00:00:00'
    AND       ph.MatterID =* m.MatterID -- Taken care
    AND       ph.PhaseSeq =* (
        SELECT  MAX( PhaseSeq )
        FROM   CMS.PHASE
        WHERE MatterID = m.MatterID -- Taken care
    )
    AND pe.PersonNo =* (
        SELECT  PersonNo
        FROM   CMS.MATTER_PERSON
        WHERE MatterID = m.MatterID
           AND       MatterPersonType = 'DEF'
    )

我尝试转换查询 2 并编写以下内容:

SELECT  m.MatterID,
    m.MatterType,
    m.HasSuppressionOrder,
    m.DateReceived,
    ISNULL (ph.OfficerID, 'No Phase'),
    ISNULL (pe.Surname, 'No Accused Registered') + ', ' + pe.GivenNames,
    m.Complexity,
    m.ProgramCode,
    m.Comments,
    m.StaffGroup,
    m.StaffSubGroup
FROM   CMS.PHASE ph
right join CMS.MATTER m ON ph.MatterID = m.MatterID
RIGHT JOIN CMS.PERSON pe ON ((SELECT  PersonNo FROM   CMS.MATTER_PERSON WHERE MatterID = m.MatterID AND MatterPersonType = 'DEF')= pe.PersonNo)
RIGHT JOIN CMS.PHASE ph2 ON ((SELECT  MAX(PhaseSeq) FROM CMS.PHASE ph WHERE ph.MatterID = m.MatterID)=ph2.PhaseSeq)
WHERE (m.DateReceived BETWEEN '2015-09-30 00:00:00' AND '2015-10-30 00:00:00')

=============================================

但是,有些不对劲。

【问题讨论】:

  • 您期待什么?什么不正确 - “语法不正确”或“数据不符合预期”?
  • 重写的 ON 条件下的那些子选择是......可疑的。我不确定我什至了解这些条件应该做什么。通常,连接条件识别一个表中的一列和另一个表中的一列,并以某种方式测试它们的关系。

标签: sql tsql outer-join


【解决方案1】:

请记住,通常可以通过交换表将右连接重写为左连接。在我看来,把它变成左连接,即使是旧式的语法,也更容易理解。

SELECT ...
FROM   CMS.MATTER m,
    CMS.PHASE ph, 
    CMS.PERSON pe
WHERE ...
AND m.MatterID *= ph.MatterID
AND (SELECT ...) *= ph.PhaseSeq
AND (SELECT ...) *= pe.PersonNo

这使得您可以将其转换为从CMS.MATTER 中选择,并左连接CMS.PHASECMS.PERSON

SELECT ...
FROM CMS.MATTER m
LEFT JOIN CMS.PHASE ph
ON ph.MatterID = m.MatterID
AND ph.PhaseSeq = (SELECT ...)
LEFT JOIN CMS.PERSON pe
ON pe.PersonNo = (SELECT ...)

【讨论】:

    【解决方案2】:

    我认为是这个(QUERY2):

    SELECT
        m.MatterID,
        m.MatterType,
        m.HasSuppressionOrder,
        m.DateReceived,
        ISNULL (ph.OfficerID, 'No Phase'),
        ISNULL (pe.Surname, 'No Accused Registered') + ', ' + pe.GivenNames,
        m.Complexity,
        m.ProgramCode,
        m.Comments,
        m.StaffGroup,
        m.StaffSubGroup
    FROM CMS.MATTER m
    INNER JOIN CMS.MATTER_PERSON mp
      ON mp.MatterID = m.MatterID AND mp.MatterPersonType = 'DEF'
    LEFT JOIN CMS.PERSON pe ON pe.PersonNo = mp.PersonNo
    OUTER APPLY
    (
      SELECT TOP 1 ph.OfficerID
      FROM CMS.PHASE ph
      WHERE ph.MatterID = m.MatterID
      ORDER BY ph.PhaseSeq DESC
    ) ph
    WHERE m.DateReceived BETWEEN '2015-09-30 00:00:00' AND '2015-10-30 00:00:00'
    

    CMS.MATTER 肯定是必须的部分,最好从它开始并让outer 加入其余表,而不是构建大量令人困惑的right 加入。

    不需要到 ph 的双重链接,但我不确定它应该是什么 - outer applycross applyMAX( PhaseSeq ) 是强制部分,所以使用cross apply 可能更正确。但是原始代码中有ISNULL(OfficerID, ''),它告诉我们可能没有相应的值......因为我们得到TOP 1 DESC,所以不需要MAX

    pe.PersonNo =* (SELECT PersonNo 应该总是返回一行 - 否则它会失败 - 所以,我想,我们可以在没有任何 TOPMAX 的情况下加入它。

    【讨论】:

      猜你喜欢
      • 2013-07-26
      • 1970-01-01
      • 2017-01-18
      • 2016-09-18
      • 2019-03-19
      • 2021-11-15
      • 1970-01-01
      • 2020-04-15
      • 2018-04-18
      相关资源
      最近更新 更多