搜索表格 - 如果找到结果,请不要搜索下一个表格

时间:2017-12-14 10:43:41

标签: sql sql-server

对于我试图制作的查询,我有一个奇怪的问题。

基本上我需要查看大约14个不同的数据库,以查看是否存在特定的合同号。如果是的话,我需要它返回Yes,但唯一的是,查询每次大约需要30分钟,因为它检查每个DB是否有相同的值(合同号只存在于一个DB中) ,随着时间的推移,它只会越来越高。

我想更改它(如果可能的话),这样如果在表1中找到了结果,它就不需要在Table2或Table3等中搜索该结果。我不知道这是否可能,这就是为什么我认为我会问专家! ;)

目前我的查询是:

select Id 
INTO #tmpContracts
from Contracts
where CreatedOn >= '2017-06-01'

select  Id,
        CASE WHEN EXISTS (select ch.CH_CODE from DimL1.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes'
             WHEN EXISTS (select ch.CH_CODE from DimL2.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes'
             WHEN EXISTS (select ch.CH_CODE from DimL3.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes'
             WHEN EXISTS (select ch.CH_CODE from DimL4.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes'
             WHEN EXISTS (select ch.CH_CODE from DimL5.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes'
             WHEN EXISTS (select ch.CH_CODE from DimL6.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes'
             WHEN EXISTS (select ch.CH_CODE from DimL7.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes'
             WHEN EXISTS (select ch.CH_CODE from DimL8.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes'
             WHEN EXISTS (select ch.CH_CODE from DimL9.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes'
             WHEN EXISTS (select ch.CH_CODE from DimL10.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes'
             WHEN EXISTS (select ch.CH_CODE from DimL11.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes'
             WHEN EXISTS (select ch.CH_CODE from DimL12.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes'
             WHEN EXISTS (select ch.CH_CODE from DimL13.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes'
             WHEN EXISTS (select ch.CH_CODE from DimL14.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes'
        ELSE 'No' END 'ProjectCodeExists'
from #tmpContracts c

drop table tmpContracts

这可以在SQL中做到吗?如果是这样,这将大大减少执行时间。

感谢您提前回复:)

4 个答案:

答案 0 :(得分:1)

我认为此修改会提升您的查询效果:

select  Id,
    CASE WHEN EXISTS (select ch.CH_CODE from DimL1.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes' ELSE
    CASE WHEN EXISTS (select ch.CH_CODE from DimL2.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes' ELSE
    CASE WHEN EXISTS (select ch.CH_CODE from DimL3.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes' ELSE
    CASE WHEN EXISTS (select ch.CH_CODE from DimL4.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes' ELSE
    CASE WHEN EXISTS (select ch.CH_CODE from DimL5.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes' ELSE
    CASE WHEN EXISTS (select ch.CH_CODE from DimL6.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes' ELSE
    CASE WHEN EXISTS (select ch.CH_CODE from DimL7.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes' ELSE
    CASE WHEN EXISTS (select ch.CH_CODE from DimL8.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes' ELSE
    CASE WHEN EXISTS (select ch.CH_CODE from DimL9.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes' ELSE
    CASE WHEN EXISTS (select ch.CH_CODE from DimL10.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes' ELSE
    CASE WHEN EXISTS (select ch.CH_CODE from DimL11.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes' ELSE
    CASE WHEN EXISTS (select ch.CH_CODE from DimL12.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes' ELSE
    CASE WHEN EXISTS (select ch.CH_CODE from DimL13.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes' ELSE
    CASE WHEN EXISTS (select ch.CH_CODE from DimL14.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) ) THEN 'Yes' ELSE
    'No' END END END END END END END END END END END END END END 'ProjectCodeExists'
from #tmpContracts c

我刚刚嵌套了所有case个。一旦满足任何案件,它应该停止评估。

答案 1 :(得分:1)

查询中的子查询针对每一行运行。我认为它耗费了大量的时间和资源。

尝试使用循环并对先前未找到的行组进行更新。

select
  Id,
  0 ProjectCodeExists
into #tmpContracts
from Contracts
where CreatedOn >= '2017-06-01'


declare @dbNum int=1
declare @query varchar(max)

while @dbNum<=14
begin

  if exists(select * from #tmpContracts where ProjectCodeExists=0)
  begin
    set @query='update c set c.ProjectCodeExists=1
      from DimL'+cast(@dbNum as varchar(2))+'.dbo.CST_COSTHEADER ch
      join #tmpContracts c on CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255))
      where c.ProjectCodeExists=0'

    print @query

    exec(@query)
  end

  set @dbNum=@dbNum+1
end

select *
from #tmpContracts

drop table #tmpContracts

我的脚本执行以下操作

if exists(select * from #tmpContracts where ProjectCodeExists=0)
  update c set c.ProjectCodeExists=1
  from DimL1.dbo.CST_COSTHEADER ch
  join #tmpContracts c on CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255))
  where c.ProjectCodeExists=0

if exists(select * from #tmpContracts where ProjectCodeExists=0)
  update c set c.ProjectCodeExists=1
  from DimL2.dbo.CST_COSTHEADER ch
  join #tmpContracts c on CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255))
  where c.ProjectCodeExists=0

if exists(select * from #tmpContracts where ProjectCodeExists=0)
  update c set c.ProjectCodeExists=1
  from DimL3.dbo.CST_COSTHEADER ch
  join #tmpContracts c on CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255))
  where c.ProjectCodeExists=0

...

if exists(select * from #tmpContracts where ProjectCodeExists=0)
  update c set c.ProjectCodeExists=1
  from DimL14.dbo.CST_COSTHEADER ch
  join #tmpContracts c on CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255))
  where c.ProjectCodeExists=0

例如。如果#tmpContracts包含100行,则查询变体中的子查询可以运行1400(100 * 14)次。

在我的版本中,只使用了14个查询到其他数据库。

答案 2 :(得分:0)

您可以通过以下方式增加上述查询的效果。 (还有很多其他的方式,但我给你最快的方式)

select 
Id 
INTO #tmpContracts
from Contracts
where CreatedOn >= '2017-06-01'


select  Id,
        CASE WHEN 
            (select COUNT(1) from DimL1.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) )
            +(select COUNT(1) from DimL2.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)))
            +(select COUNT(1) from DimL3.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)))
            +(select COUNT(1) from DimL4.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)))
            +(select COUNT(1) from DimL5.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) )
            +(select COUNT(1) from DimL6.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) )
            +(select COUNT(1) from DimL7.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) )
            +(select COUNT(1) from DimL8.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) )
            +(select COUNT(1) from DimL9.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) )
            +(select COUNT(1) from DimL10.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) )
            +(select COUNT(1) from DimL11.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) )
            +(select COUNT(1) from DimL12.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) )
            +(select COUNT(1) from DimL13.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) )
            +(select COUNT(1) from DimL14.dbo.CST_COSTHEADER ch where CAST(c.Id as varchar(255)) = CAST(ch.CH_CODE as varchar(255)) )
            > 0 THEN 'Yes'
        ELSE 'No' END 'ProjectCodeExists'
from #tmpContracts c

drop table tmpContracts

答案 3 :(得分:0)

虽然我很欣赏其他答案正在帮助您直接发布的内容,但我认为它们是对数据库数据结构方式以及您如何查询的更深层次问题的帮助

世界上没有办法在14个不同的表中查找单个适当索引的值应该花费30分钟,无论它们是否在不同的数据库中。即使您在临时表中有一万份合同,加入其他14个表,也不应该花费30分钟 - 而这些甚至不是“我在每个表中都有一些我想要的数据”的意义上的连接 - 这些是“这张桌子有没有我感兴趣的数据?”意义上的联想。 (这个问题可以通过索引来回答,甚至没有打到表格)

我注意到你的查询转换了被搜索列的数据类型 - 不要这样做,因为它通常会破坏在该列上使用索引的任何能力。如果ch.CH_CODE是一个guid(例如),那么请确保你的c.Id也是一个guid(当你制作合同临时表时这样做)然后你不会转换潜在的数十亿行并查看它们全部;你的数据库可以简单地进行索引查找,以了解查询的整个答案“表中是否存在值X”。如果您没有从这篇文章中删除任何其他内容,请选择:“索引与否,如果您有一个数据类型为X的搜索词,以及要查看数据类型Y的十亿行,则总是更好将单个类型X转换为Y型,而不是将十亿个Ys转换为X“

如果您要坚持以这种方式破坏数据,那么请考虑在合约表中添加一个标记,告诉您在哪里可以找到您要查找的数据。我强烈建议您重新考虑一下您的数据存储策略,这样您就不必运行回答“嗯......我现在将数据留在哪一千个表中的哪一个?”的问题的查询。 - 你应该知道你的数据在哪里