是否有更有效的查询此任务?

时间:2019-08-02 10:56:20

标签: sql sql-server

一条消息定义为2条类型为0的消息之间的所有消息。

我需要在表中找到第一个块 确保所有行都存在于块中

我的解决方案:

SELECT MSG FROM (   
    SELECT 
    CASE  
        WHEN type = 83 AND next_type = 84 THEN REPLACE(CONCAT(MSG,next_msg),' ', '')
        WHEN type = 83 AND next_type != 84 THEN MSG
        WHEN type = 83 AND next_type IS NULL THEN MSG       
, ROW_NUMBER() OVER(order by id) AS row_num 

                ) AS tmp5
WHERE MSG IS NOT NULL

2 个答案:

答案 0 :(得分:0)

如果我遵循逻辑,则:

MyCustomTypeCollection

select concat(msg, (case when next_type = 84 then next_msg else '' end)) from (select m.*, lead(type) over (order by id) as next_id, lead(msg) over (order by id) as next_msg, sum(case when type = 0 then 1 else 0 end) over (order by id) as num_0s from Messages m ) m where num0s % 2 = 1 and -- in between two 0s type = 83; 的计数提供了一种在两个0之间查找消息的方法。其余的只是对0进行过滤并进行串联。

答案 1 :(得分:0)

您的方法似乎很好。您首先选择第一个和第二个零类型ID,并且仅对它们之间的ID起作用。但是,我不明白您为什么将ID与它们的相对位置(row_num = id)进行比较。这迫使您使用表中的所有消息创建一个cross join,而不是仅仅使用inner joinexists子句或between子句。

这是查询的简化版本,用于批量查询消息:

with limits as
(
  select min(id) as id01, max(id) as id02
  from (select top 2 id, type from messages where type = 0 order by id) first2
)
select case when next_type = 84 then msg + next_msg else msg end
from
(
  select
    type, lead(type) over(order by id) as next_type,
    msg, lead(msg) over(order by id) as next_msg  
  from messages m
  where id > (select id01 from limits)
    and id < (select id02 from limits)
) firstbulk
where type = 83;

您希望messages(type, id)上的索引可以快速获取零类型ID,而messages(id)上的索引当然可以快速选择批量中的行。

演示:https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=eecb6383b9daa6963e08dde6a0dd30a1

编辑:您希望内置间隙检测。使用COUNT(*)OVER()和零类型ID来查看ID之间是否存在与预期一样多的行。

with limits as
(
  select min(id) as id01, max(id) as id02
  from (select top 2 id, type from messages where type = 0 order by id) first2
)
select case when gaps <> 0 then 'Gap detected'
            when next_type = 84 then msg + next_msg 
            else msg end
from
(
  select
    m.type, lead(m.type) over(order by m.id) as next_type,
    m.msg, lead(m.msg) over(order by m.id) as next_msg,
    l.id02 - l.id01 - count(*) over () - 1 as gaps
  from messages m
  join limits l on l.id01 < m.id and l.id02 > m.id
) firstbulk
where type = 83;

演示:https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=909228fd2696b419d14cd4a1c2c220a3