【问题标题】:What's the less expensive way to find missing records for this table structure?查找此表结构的缺失记录的更便宜的方法是什么?
【发布时间】:2020-05-14 20:07:52
【问题描述】:

我有一个主数据流表,格式类似于下面的流表。每个 idtype 都有一组可能的 idname

我正在尝试找出哪个 id 缺少 idname。我还创建了一个表,其中包含所有 idtype 及其 idname 值,如 Stream Info Table 所示。

我可以灵活地使用解决方案来查找这些值,它不是一个固定的查找表,但我需要知道缺少哪个和 id 而不仅仅是缺失值的数量。

Stream Table
╔════╦═════════════════════════╦══════════╦════════╦═══════════╗
║ id ║       idtimestamp       ║  idtype  ║ idname ║  idvalue  ║
╠════╬═════════════════════════╬══════════╬════════╬═══════════╣
║  1 ║ 2020-05-15 10:49:58.773 ║ external ║ body   ║ round     ║
║  1 ║ 2020-05-15 10:49:58.773 ║ external ║ genre  ║ all       ║
║  1 ║ 2020-05-15 10:49:58.773 ║ external ║ size   ║ uniform   ║
║  2 ║ 2020-05-15 10:49:58.773 ║ internal ║ batch  ║ batchname ║
║  2 ║ 2020-05-15 10:49:58.773 ║ internal ║ link   ║ quad      ║
╚════╩═════════════════════════╩══════════╩════════╩═══════════╝

Stream Info Table
╔══════════╦════════╗
║  idtype  ║ idname ║
╠══════════╬════════╣
║ external ║ blue   ║
║ external ║ body   ║
║ external ║ genre  ║
║ external ║ size   ║
║ internal ║ batch  ║
║ internal ║ link   ║
║ internal ║ whyte  ║
╚══════════╩════════╝

对于给定的数据集,我希望输出这些数据:

╔════╦═════════════════════════╦══════════╦════════╦
║ id ║       idtimestamp       ║  idtype  ║ idname ║  
╠════╬═════════════════════════╬══════════╬════════╬
║  1 ║ 2020-05-14 20:48:50.540 ║ external ║ blue   ║ 
║  2 ║ 2020-05-14 20:48:50.540 ║ internal ║ whyte  ║  
╚════╩═════════════════════════╩══════════╩════════╩

示例数据集:

drop table if exists #stream_data
create table #stream_data (id int, idtimestamp datetime, idtype varchar(30), idname varchar(60), idvalue varchar(100))
insert into #stream_data
select '1' , getdate() , 'external' , 'body' , 'round' union
select '1' , getdate() , 'external' , 'size' , 'uniform' union
select '1' , getdate() , 'external' , 'genre' , 'all' union
select '2' , getdate() , 'internal' , 'batch' , 'batchname' union
select '2' , getdate() , 'internal' , 'link' , 'quad' 


drop table if exists #stream_info 
create table #stream_info (idtype varchar(30), idname varchar(60))
insert into #stream_info
select 'external' , 'body' union
select 'external' , 'size' union
select 'external' , 'genre' union
select 'external' , 'blue' union
select 'internal' , 'batch' union 
select 'internal' , 'link' union
select 'internal' , 'whyte'

【问题讨论】:

  • 你的尝试是什么,是什么让你觉得它很贵?
  • 请在代码问题中给出minimal reproducible example--包括剪切、粘贴和可运行的最小代码和以代码形式给出的最小代表性数据。对于包含 DBMS 和 DDL 的 SQL,包括约束、索引和表格初始化。对于包括 EXPLAIN 结果和统计信息的 SQL 性能。请研究和总结。对于包括优化/性能基础的 SQL——立即导致索引、计划、统计和 SARGability。 Tips for asking a good SQL question 在您学习并应用了这些基础知识后,请重新优化。 How to Ask
  • 工程中没有“更好”/“最好”之类的东西,除非定义它。同样不幸的是,所有合理的实际定义都需要大量的经验,以及与对细节的混乱敏感度相互作用的大量因素。进行简单的设计。当您通过测量证明您可以想到的设计和所有替代方案都存在问题时(无论当时意味着什么),然后提出一个非常具体的问题。这也应该定义“更好”/“最好”。 Strategy for “Which is better” questions
  • @philipxy 感谢您的深思熟虑的评论。但是,我不是在这里寻找XY Problem 场景。我已经发布了我想要实现的目标,并且我愿意听取其他工程师的建议,这是 stackoverflow 的基本原则。
  • 我的 cmets 与 XY 问题无关。 help center

标签: sql-server tsql join lookup missing-data


【解决方案1】:

类似:

select *
from #stream_data sd
where not exists
(
  select *
  from #stream_info si
  where si.idtype = sd.idtype
    and si.idname = sd.idname
)

输出

id  idtimestamp             idtype     idname  idvalue
--- ----------------------- ---------- ------- -----------
1   2020-05-14 15:17:20.487 external   batch   batchname
2   2020-05-14 15:17:20.487 internal   float   whyte

【讨论】:

  • 抱歉,我弄乱了数据。反过来,#stream_info 比#stream_data 获得的信息更多。我已经更新了问题。
【解决方案2】:
DECLARE     @StreamData TABLE   (id int, idtimestamp datetime, idtype varchar(30), idname varchar(60), idvalue varchar(100))
INSERT INTO @StreamData VALUES
            ('1' , getdate() , 'external' , 'body'  , 'round'       )
        ,   ('1' , getdate() , 'external' , 'genre' , 'all'         )
        ,   ('1' , getdate() , 'external' , 'size'  , 'uniform'     )
        ,   ('2' , getdate() , 'internal' , 'batch' , 'batchname'   )
        ,   ('2' , getdate() , 'internal' , 'link'  , 'quad'        )

DECLARE     @StreamInfo TABLE   (idtype varchar(30), idname varchar(60))
INSERT INTO @StreamInfo VALUES
            ('external' , 'blue'    )
        ,   ('external' , 'body'    )
        ,   ('external' , 'genre'   )
        ,   ('external' , 'size'    )
        ,   ('internal' , 'batch'   )
        ,   ('internal' , 'link'    )
        ,   ('internal' , 'whyte'    )

-- With LEFT JOIN you are getting all of the rows of the StreamInfo Table
-- With the WHERE Clause you are just getting those without a matching row in the StreamData Table
SELECT  SI.*
FROM           @StreamInfo SI
    LEFT JOIN  @StreamData SD   ON  SD.idtype   =   SI.idtype
                                AND SI.idname   =   SD.idname
WHERE           SD.idname IS NULL

【讨论】:

  • 抱歉 - 我弄乱了数据。查找相反,我试图通过查看#stream_info 来找出#stream_table 中是否有任何丢失的记录。更新了问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-19
  • 2011-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多