【问题标题】:How to select distinct rows, but repeat if it has a different row between the equal ones如何选择不同的行,但如果在相等的行之间有不同的行,则重复
【发布时间】:2017-04-11 03:20:18
【问题描述】:

有这样的数据:

id   text   bit  date
1    row     1   2016-11-24
2    row     1   2016-11-25
3    row     0   2016-11-26
4    row     1   2016-11-27

我想根据文本和位列不同的位置来选择数据,但基于某种顺序,在这种情况下是 id,数据在两个相同的行之间发生变化,它应该在选择时复制这一行。

所以,如果我在 SQL 上使用distinct,我会得到第 1 行和第 3 行,但我想检索第 1、3 和 4 行,因为即使第 1 行和第 4 行相同,第 3 行在排序时介于两者之间身份证。

使用更大的数据集,例如:

id   text   bit  date
1    row     1   2016-11-24
2    row     1   2016-11-25
3    row     0   2016-11-26
4    row     1   2016-11-27
5    foo     1   2016-11-28
6    bar     1   2016-11-29
7    row     1   2016-11-30
8    row     0   2016-12-01
9    row     0   2016-12-02
10   row     1   2016-12-03

同样,在 text 和 bit 列上选择 distinct,查询将检索第 1、3、5 和 6 行,但实际上我想要第 1、3、4、5、6、7、8 和 10 行。

【问题讨论】:

  • 对不起,如果标题有点混乱,但我找不到更好的方式。
  • 请显示一个更大的数据集,其中显示所有边缘情况。我不遵循你的逻辑。
  • 添加了一个数据不多的案例,看看是否有帮助。

标签: sql-server select distinct


【解决方案1】:
;with tb(id,[text],[bit],[date]) AS (
      SELECT  1,'row',1,'2016-11-24' union
      SELECT  2,'row',1,'2016-11-25' union
      SELECT  3,'row',0,'2016-11-26' union
      SELECT  4,'row',1,'2016-11-27' union
      SELECT  5,'foo',1,'2016-11-28' union
      SELECT  6,'bar',1,'2016-11-29' union
      SELECT  7,'row',1,'2016-11-30' union
      SELECT  8,'row',0,'2016-12-01' union
      SELECT  9,'row',0,'2016-12-02' union
      SELECT  10,'row',1,'2016-12-03')

    select t1.* from tb as t1
    OUTER APPLY (select top 1 [text],[bit] from tb as tt where tt.id<t1.id order by id desc ) as t2
    where t1.[text]!=isnull(t2.[text],'') or t1.[bit]!=isnull(t2.[bit],1-t1.[bit])

结果集:

1排1 2016-11-24 3 行 0 2016-11-26 4排1 2016-11-27 5 富 1 2016-11-28 6 条 1 2016-11-29 7排1 2016-11-30 8 行 0 2016-12-01 10排1 2016-12-03

【讨论】:

    【解决方案2】:

    看来您需要一个逐行运算符。您需要知道新行是否与前一行相同。如果是,忽略它,如果不是,保留它。这是我的解决方案:

     declare @text varchar(100)=(select [text] from Mytable where id = 1)
     declare @bit bit = (select [bit] from Mytable where id = 1)
     declare @Newtext varchar(100)
     declare @Newbit bit
     declare @Mytable table(id int, [text] varchar(100), [bit] bit) 
     Insert into  @Mytable select id,text, bit from Mytable where id = 1
     declare @counter int =2
    
     while @counter<=(select COUNT(*) from MyTable)
     Begin
        select @Newtext=(select [text] from Mytable where id = @counter)
        select @Newbit=(select [bit] from Mytable where id = @counter)
    
        IF @Newtext!=@text or @Newbit!=@bit
        Begin   
            Insert into @Mytable 
            select * from Mytable where id = @counter
        End
        set @text = @Newtext
        set @bit = @Newbit;
        set @counter = @counter+1
     END
     select * from @Mytable
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-22
      • 2020-10-01
      • 1970-01-01
      • 2018-11-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-10
      • 2017-12-31
      相关资源
      最近更新 更多