sql-server 连接不同表中的两列并将它们用作WHERE子句

jmo0nnb3  于 2022-10-31  发布在  其他
关注(0)|答案(2)|浏览(146)
select top 100 * 
from ProductionPeriodic.dbo.ScanDataRaw
where sdr_ID in (
    select concat(rsw_dept, rsw_rsm_id_fk) 
    from [dbo].[RollSheetArchiveDetails] rsad
    inner join dbo.RollSheetMain rsm on rsad.rsw_rsm_id_fk = rsm.rsm_id 
    where rsw_PoNo = 'UHB800008'
    and rsm_status = 'R'
)
and sdr_ScanDate = '30/09/2022'

sdr_ScanDate是一个字符串。
有两个串联的值。
但是,查询不会停止执行

k4emjkb1

k4emjkb11#

我的假设是子查询 * 应该 * 运行得很快,但我的假设是查询优化器在应用过滤器之前进行完全连接。
我首先要确保

select rsw_dept, rsw_rsm_id_fk 
    from [dbo].[RollSheetArchiveDetails] rsad
    inner join dbo.RollSheetMain rsm on rsad.rsw_rsm_id_fk = rsm.rsm_id 
    where rsw_PoNo = 'UHB800008'
    and rsm_status = 'R'

如果不是,您可能需要添加索引或重新处理以与现有的索引保持一致。
在那之后,还需要这样的情况:

SELECT TOP 100 * 
FROM   ProductionPeriodic.dbo.ScanDataRaw
WHERE  sdr_ID IN ('id1', 'id2')
AND    sdr_ScanDate = '30/09/2022'

也运行得很快。同样,如果不是单独优化这个部分。
如果这两种情况都是这样,那么优化器可能会被相关子查询绊倒。您可能希望将此连接设置为正确的连接:

SELECT TOP 100 ScanDataRaw.* 
FROM        ProductionPeriodic.dbo.ScanDataRaw
INNER JOIN  (   SELECT DISTINCT 
                    sw_dept, 
                    rsw_rsm_id_fk 
                FROM        [dbo].[RollSheetArchiveDetails]
                INNER JOIN  dbo.RollSheetMain 
                ON          RollSheetArchiveDetails.rsw_rsm_id_fk = RollSheetMain.rsm_id 
                WHERE       rsw_PoNo = 'UHB800008'
                AND         rsm_status = 'R'
            ) AS IdParts
ON          ScanDataRaw.sdr_ID = IdParts.rsw_dept + IdParts.rsw_rsm_id_fk
WHERE       ScanDataRaw.sdr_ScanDate = '30/09/2022'

如果查询最佳化行程程式仍然无法判断IdParts子查询执行速度快且传回的数据列少,您可以尝试胁迫它使用INNER LOOP JOIN、INNER HASH JOIN和INNER MERGE JOIN来尝试3个实体链接中的每一个,而且您可以按照ScanDataRaw JOIN IdParts顺序和IdParts JOIN ScanDataRaw顺序来尝试它们。这6个选项中最快的选项都可以成为您的查询。
不过,理想情况下,它将能够自己解决这个问题,而不必指定特定的物理连接。

vybvopom

vybvopom2#

好奇心起:如果希望更快地进行测试和估计时间,则应尝试将top放在子查询内。
一些优化:
1.检查索引与Where列
1.如果有多个值,则添加Distinct以减少处理select distinct concat(rsw_dept, rsw_rsm_id_fk)
以下是处理此问题的其他方法:
测试内部链接:

select top 100 ProductionPeriodic.dbo.ScanDataRaw.* 
from ProductionPeriodic.dbo.ScanDataRaw 
INNER JOIN (
    select distinct concat(rsw_dept, rsw_rsm_id_fk)  as sdr_ID_FILTER
    from [dbo].[RollSheetArchiveDetails] rsad
    inner join dbo.RollSheetMain rsm on rsad.rsw_rsm_id_fk = rsm.rsm_id 
    where rsw_PoNo = 'UHB800008'
    and rsm_status = 'R'
) Filtering
    on sdr_ID =  Filtering.sdr_ID_FILTER
WHERE sdr_ScanDate = '20220930'

测试存在的位置:

select top 100 ScanDataRaw.* 
from ProductionPeriodic.dbo.ScanDataRaw AS ScanDataRaw
WHERE sdr_ScanDate = '20220930' 
AND EXISTS 
(select 1   
    from [dbo].[RollSheetArchiveDetails] rsad
    inner join dbo.RollSheetMain rsm on rsad.rsw_rsm_id_fk = rsm.rsm_id 
    where rsw_PoNo = 'UHB800008'
    and rsm_status = 'R' AND concat(rsw_dept, rsw_rsm_id_fk)=ScanDataRaw.sdr_ID
)

备注:在查询中定义日期时,应使用全球标准化的日期格式“YYYYMMDD”。

相关问题