【问题标题】:Queries: Using multiple columns with same name but from different tables as conditions for the WHERE clause?查询:使用多个具有相同名称但来自不同表的列作为 WHERE 子句的条件?
【发布时间】:2021-03-16 17:24:30
【问题描述】:

我想使用来自不同表的 SOME_DATE 和 ANOTHER_DATE 列作为我查询的 WHERE 子句条件的一部分。

如果我从下面的查询中删除 AND ATT.[SOME_DATE] <= '02 december 2020' AND ATT.[ANOTHER_DATE] >= '02 december 2020',我只能让它工作:

;WITH cs AS 
( 
    SELECT 
        t.LKJ_UID,
        t.ITEM_UID,
        t.[I_T_UID], 
        t.[I_I_CD], 
        t.[L_DS], 
        t.[SOME_DATE], 
        t.[ANOTHER_DATE], 
        t.[AN_DATED], 
        t.[LS_E_DATE], 
        t.[LS_E_UST_UID], 
        t.[PTU_UID], 
        t.[FMT_UID], 
        t.[DG_LT], 
        t.[DG_A], 
        t.[OD], 
        t.[NTH], 
        t.[BJU], 
        t.[BJI], 
        t.[LOK], 
        t.[JUT], 
        ATT.[FG_UID], 
        ATT.[RTU_UID], 
        ATT.[LKJ_CD], 
        ATT.[LKJ_NAME], 
        ATT.[LKJ_TYPE_UID], 
        ATT.[LKJ_LENGTH], 
        ATT.[LCA_KIP_UID], 
        ATT.[CL_WD], 
        ATT.[LCA_OCC_LC_UID], 
        ATT.[SJ_K], 
        ATT.[SJ_J],
        ATT.SOME_DATE as SA_SOME_DATE,
        ATT.ANOTHER_DATE as SA_ANOTHER_DATE
       
    FROM 
        CATT AS t
    LEFT OUTER JOIN 
        ATT ON t.LKJ_uid = ATT.LKJ_uid
    
    WHERE 
        t.[SOME_DATE] <= '02 december 2020'
        AND t.[ANOTHER_DATE] >= '02 december 2020'
        AND ATT.[SOME_DATE] <= '02 december 2020'
        AND ATT.[ANOTHER_DATE] >= '02 december 2020'

    ORDER BY t.[ITEM_UID]
        OFFSET 24 * 0 ROWS
    FETCH NEXT 24 ROWS ONLY
) 

SELECT *
FROM cs
ORDER BY 
cs.ITEM_UID

仅当我删除最后一个示例的这一部分时,它才会起作用,但我需要它遵守所有 4 个条件,而不仅仅是两个:

AND ATT.[SOME_DATE] <= '02 december 2020'
AND ATT.[ANOTHER_DATE] >= '02 december 2020'

感谢您的帮助

编辑:(响应 Shawnt00 的回答)

此查询返回 72k 行,而您建议的更改返回 160 万条记录:

SELECT dbo.CATT.*, 
       dbo.ATT.* 
FROM   dbo.CATT 
       LEFT OUTER JOIN dbo.ATT 
               ON dbo.CATT.LKJ_uid = 
                  dbo.ATT.LKJ_uid 
WHERE  ( dbo.CATT.SOME_DATE <= 
         CONVERT(DATETIME, '02 december 2020' 
                , 
                102) ) 
       AND ( dbo.CATT.ANOTHER_DATE >= 
             CONVERT(DATETIME, '02 december 2020', 
                 102) ) 
       AND ( dbo.ATT.SOME_DATE <= 
             CONVERT(DATETIME, '02 december 2020', 
                 102) ) 
       AND ( dbo.ATT.ANOTHER_DATE >= 
             CONVERT(DATETIME, '02 december 2020', 
             102) )

【问题讨论】:

  • 几件事:“永远执行”听起来像是一个性能问题。您的数据集有多大,是否有可用的索引? 您的查询彼此完全不同,不确定比较性能是否有意义,麻烦的版本有(1)带有offsetfetch next子句的额外分页,(2)02 december 2020没有日期转换, (3) 额外的 CTE 构造和 (4) 在 CTE 之外使用 order by 子句进行额外排序... 上一个版本中的 left join隐式 inner join 到期到where 子句中该表上的范围。
  • @Sander 有 72k 条记录,应用了所有四个 WHERE 条件。如果我删除最后两个 WHERE 条件(这使得第二个查询工作),则有 160 万条记录。我不完全相信这是一个性能问题,因为如果我从第二个查询中删除两个 WHERE 条件,即使有额外的分页、CTE 等,查询也会正常工作。 (在原帖中解释)
  • @NickyLarson 你所说的“工作”是什么意思——它会引发错误吗?是不是跑了很久没有完成?
  • 性能肯定会迫在眉睫我认为 start_date 和 end_date 必须被索引还添加过滤器以排除 start_date 或 end_date 其中 null ex。 start_date not null and end_date not null
  • order by 会杀死整个系统,尝试在没有 order by 的情况下运行并查看结果 - 注意:作为一般规则,对 SELECT 子句中的项目执行 CAST 或 CONVERT 几乎没有任何成本。 (请注意,WHERE 或 ON 子句中的 CAST 或 CONVERT 可能非常昂贵,因为它们会使 SQL Server 无法有效使用索引)。

标签: sql ssms sql-server-2014 querying


【解决方案1】:

将条件移动到联接中。从where 中删除它。

LEFT OUTER JOIN 
        section_attributes ON t.section_uid = section_attributes.section_uid
    AND SECTION_ATTRIBUTES.START_DATE <= '02 december 2020'
    AND SECTION_ATTRIBUTES.END_DATE >= '02 december 2020'

【讨论】:

  • 谢谢你,成功了。您介意解释一下为什么条件不能保留在WHERE 子句中吗?
  • 我说得太早了。您建议的更改返回 160 万条记录,而如果我运行刚刚添加到“编辑”下的原始帖子的查询,它会返回 72k 结果。 (应该返回什么)
  • 为什么要使用外连接?
  • 我刚刚收到确认,它需要是外部联接,因为联接表中是否没有记录无关紧要。在这种情况下,答案是正确的,它确实应该返回 160 万条记录。道歉
猜你喜欢
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-12
相关资源
最近更新 更多