选择连续出现多次的记录

Posted

技术标签:

【中文标题】选择连续出现多次的记录【英文标题】:Selecting records that appear several times in a row 【发布时间】:2021-04-09 14:51:52 【问题描述】:

我的问题是我想选择一些连续出现的记录。 例如我们有这样的表:

x
x
x
y
y
x
x
y

查询应该给出这样的答案:

x   3
y   2
x   2
y   1

【问题讨论】:

您可能需要第二列。也许是一个自动增加的 id 列?如果您无法获得第二列,则在 excel 中也可能更容易。 请始终声明您的数据库系统和版本。 SQL 方言差异很大。 最后一个结果行y|1 与标题不一致。请澄清。 【参考方案1】:

SQL 表代表无序 集合。只有当有一列指定顺序时,您的问题才有意义。如果是这样,您可以使用差异行数来确定组,然后聚合:

select col1, count(*)
from (select t.*,
             row_number() over (order by <ordering col>) as seqnum,
             row_number() over (partition by col1 order by <ordering col>) as seqnum_2
      from t
     ) t
group by col1, (seqnum - seqnum_2)

【讨论】:

抱歉,一定有什么地方出错了——它告诉我:'*' 附近的语法不正确。 @beginneeeeer2021 。 . .查询中唯一的*s 是count(*)t.*。两者在语法上都是正确的。 还有一个问题 - 2、6 和 6 行中的 t 是什么? :) @beginneeeeer2021 。 . .那是from 子句中的表名和括号后面的表别名。您的问题没有指定表名,所以我只使用t【参考方案2】:

我做了一个 SQL Fiddle http://sqlfiddle.com/#!18/f8900/5

CREATE TABLE [dbo].[SomeTable](
    [data] [nchar](1) NULL,
    [id] [int] IDENTITY(1,1) NOT NULL
);

INSERT INTO SomeTable
    ([data])
VALUES
    ('x'),
    ('x'),
    ('x'),
    ('y'),
    ('y'),
    ('x'),
    ('x'),
    ('y')
;

select * from SomeTable;

WITH SomeTable_CTE (Data, total, BaseId, NextId)
AS
(
SELECT 
    Data,
    1 as total,
    Id as BaseId,
    Id+1 as NextId
    FROM SomeTable
        where not exists(
            Select * from SomeTable Previous
            where Previous.Id+1 = SomeTable.Id 
            and Previous.Data = SomeTable.Data)
UNION ALL
select SomeTable_CTE.Data, SomeTable_CTE.total+1, SomeTable_CTE.BaseId as BaseId, SomeTable.Id+1 as NextId
from SomeTable_CTE inner join SomeTable on
SomeTable.Data = SomeTable_CTE.Data
and 
SomeTable.Id = SomeTable_CTE.NextId
)
SELECT Data, max(total)   as total
FROM SomeTable_CTE
group by Data, BaseId
order by BaseId

【讨论】:

【参考方案3】:

房间里的大象是确定行顺序的缺失列。

SELECT col1, count(*)
FROM  (
   SELECT col1, order_column
        , row_number() OVER (ORDER BY order_column)
        - row_number() OVER (PARTITION BY col1 ORDER BY order_column) AS grp
   FROM tbl
   ) t
GROUP  BY col1, grp
ORDER  BY min(order_column);

要排除只有一行的分区,请添加HAVING 子句:

SELECT col1, count(*)
FROM  (
   SELECT col1, order_column
        , row_number() OVER (ORDER BY order_column)
        - row_number() OVER (PARTITION BY col1 ORDER BY order_column) AS grp
   FROM tbl
   ) t
GROUP  BY col1, grp
HAVING count(*) > 1
ORDER  BY min(order_column);

db小提琴here

添加最后一个 ORDER BY 以保持原始顺序(以及有意义的结果)。您可能还想添加min(order_column) 之类的列。

相关:

Find the longest streak of perfect scores per player Select longest continuous sequence Group by repeating attribute

【讨论】:

这里的grp是什么? 只是别名是的? 看到AS grp?这是计算的“组号”的列别名。链接答案中有充分的解释。我添加了另一个链接 还有一个问题:第 6 行和第 7 行应该有表 jest 的名称?例如 cattable 而不是 od t 和 tbl?因为我有一些错误语法 t 在我的查询中是来自子查询的派生表所需的别名。可以是任何个有效标识符。喜欢cattabletbl 是基础表实际名称的占位符。

以上是关于选择连续出现多次的记录的主要内容,如果未能解决你的问题,请参考以下文章

PPT连续使用箭头等工具,避免多次重复选择,提升效率

PPT连续使用箭头等工具,避免多次重复选择,提升效率

连续选择编号较低的记录

访问连续表单:记录状态

从表中选择最后修改的数据记录

Chrome 证书选择出现多次