【问题标题】:SQL Server - don't select if not uniqueSQL Server - 如果不是唯一的,请不要选择
【发布时间】:2016-12-01 18:22:16
【问题描述】:

我发现了很多关于选择唯一的问题,但没有完全忽略非唯一。

我不只是想要每个值的第一个,我想主动避免所有值出现多次的记录。

MyTable
id | col1 | col2
1  | a    | Some thing
2  | b    | Stuff
3  | b    | Other stuff
4  | c    | Some other thing

SELECT * FROM MyTable WHERE [col1 is unique]

应该只返回第 1 行和第 4 行,因为在 col1b 出现不止一次。

【问题讨论】:

    标签: sql sql-server tsql select


    【解决方案1】:

    内部选择仅获得唯一的col1。要获得完整的行,您还需要使用外部选择

    select * from your_table
    where col1 in 
    (
      select col1 
      from your_table
      group by col1
      having count(*) = 1
    )
    

    【讨论】:

    • @Matt 。 . .你的评论没有意义。 Juergen 的回答对我来说似乎是正确的(除了NULL 值的单例可能例外,但假设 not-NULL 是合理的)。
    • @GordonLinoff 同意
    • @GordonLinoff 我从来没有说过它不起作用事实上我明确评论过它确实起作用,我对答案中说“你也需要使用外部选择”的部分提出异议,因为您实际上不需要考虑到 OP 正在寻找唯一记​​录。如果要查找重复/非唯一,则更需要这种技术。当使用 MAX 或 MIN 等其余列的聚合来查找唯一值时就足够了,我的回答表明了这种可能性。
    【解决方案2】:

    试试这个

    with tmp as (
    select f1.*, count(*) over(partition by col1 order by col1) nb
    from MyTable f1
    )
    select * from Mytable f2 inner join tmp f3
    on f2.id=f3.id and f3.nb=1
    

    select * from (
          select f1.*, count(*) over(partition by col1) nb
          from MyTable f1
                  ) f2 
    where f2.nb=1
    

    with tmp as (
    select col1 from MyTable 
    group by col1 
    having count(*)=1
    )
    select * from MyTable f1
    where exists
    (
     select * from tmp f2
     where f1.col1=f2.col1
    )
    

    【讨论】:

      【解决方案3】:

      我同意使用COUNT(*) OVEREsperento57's answer。但是因为您想要 Col1 唯一的记录,您实际上也可以在单个 group by 中进行聚合。

      DECLARE @MyTable AS TABLE (id INT, col1 CHAR(1), col2 VARCHAR(100))
      INSERT INTO @MyTable VALUES (1,'a','Some thing'),(2,'b','Stuff'),
      
      (3,'b','Other stuff'),(4,'c','Some other thing')
      
      SELECT
          MIN(Id) as Id
          ,Col1
          ,MIN(col2) as col2
      FROM
          @MyTable
      GROUP BY
          Col1
      HAVING
          COUNT(*) = 1
      

      【讨论】:

      • 注意:不是所有的数据类型都可以在这里使用。哪些类型可以工作,哪些不工作取决于所使用的 SQL Server 版本。
      • 为什么你应该在回答中说你投了赞成票
      • @Sami 我展示了 Juergen 的替代方案来证明一个观点。我的偏好以及我通常会建议的是 Esperrento 回答的 COUNT(*) OVER,我说得很清楚。您现在评论了一些通用的 cmets,而不是关于答案是正确的、错误的还是需要调整的,有什么特别困扰您的事情吗?
      【解决方案4】:

      我认为最简单的方法是使用窗口函数:

      SELECT t.*
      FROM (SELECT t.*, COUNT(*) OVER (PARTITION BY col1) as cnt
            FROM MyTable t
           ) t
      WHERE cnt = 1;
      

      如果表上有主键,那么最快的方法(带有适当的索引)可能是:

      select t.*
      from MyTable t
      where not exists (select 1 from mytable t2 where t2.col = t.col and t2.pkid <> t.pkid);
      

      为此,您需要MyTable(col, pkid) 上的索引。

      【讨论】:

        猜你喜欢
        • 2019-04-13
        • 1970-01-01
        • 1970-01-01
        • 2011-02-20
        • 1970-01-01
        • 1970-01-01
        • 2014-12-01
        • 2014-06-13
        • 1970-01-01
        相关资源
        最近更新 更多