简体   繁体   English

SQL难题(查找列值的首次出现)

[英]A SQL puzzle (find the first occurrence of a column value)

CIs there an easy way where I can find the first occurrence of a row that has a particular value in a column? CI有一种简单的方法可以找到列中具有特定值的行的第一次出现? For example suppose I have these two tables 例如,假设我有这两个表

Alphabet
A
B
C
D


Alphabet    Usage
A           Apple
B           Bat
D           Dog
A           Amateur
A           Arsenal
C           Cat
B           Ball
D           Drum

What would be an easy way to select everything in the first table and the first usage of it in the second table? 在第一个表中选择所有内容并在第二个表中选择它的第一次使用的简便方法是什么?

Expected Output: 预期产量:

Alphabet    Usage
A           Apple
B           Bat
C           Cat
D           Dog

You should be able to apply row_number() . 您应该能够应用row_number() However when using row_number there is an order that needs to be provided. 但是,在使用row_number时,需要提供一个顺序。

This first example uses a order by usage but the problem is that that will not be in the order of first in the table, it will be in alphabetical order: 第一个例子通过使用顺序usage ,但问题是,不会在第一表中的顺序,这将是按字母顺序排列:

select alphabet, usage
from
(
  select t1.alphabet,
    t2.usage,
    row_number() over(partition by t1.alphabet order by t2.usage) rn
  from table1 t1
  inner join table2 t2
    on t1.alphabet = t2.alphabet
) src
where rn =1

See SQL Fiddle with Demo . 请参阅带有演示的SQL Fiddle

If you do not have a numeric id field to guarantee the order of the first one entered. 如果您没有数字ID字段来保证第一个输入的顺序。 You might be able to use: 可能可以使用:

select alphabet, usage
from
(
  select t1.alphabet,
    t2.usage,
    row_number() over(partition by t1.alphabet order by (select 1)) rn
  from table1 t1
  inner join table2 t2
    on t1.alphabet = t2.alphabet
) src
where rn =1

See SQL Fiddle with Demo . 请参阅带有演示的SQL Fiddle

As @Aaron pointed out in the comments, that order is not guaranteed with using this method and the behavior can change. 正如@Aaron在评论中指出的那样,使用此方法不能保证顺序,并且行为可以更改。

Ideally, you should have sort type of column that will allow you distinguish the first occurrence of your data, ie datetime, id, etc. Since there is no order on data in a table, you apply the order using order by 理想情况下,您应该具有一种排序类型的列,该列将使您能够区分数据的首次出现,即日期时间,ID等。由于表中的数据没有顺序,因此可以使用order by来应用该顺序

You cannot, unless you have an ordering on the second table. 您不能,除非您在第二张桌子上有订单。 SQL Tables are inherently unordered, so you would need a column that specifies an insert time or an auto-incrementing id. SQL表本质上是无序的,因此您需要一列来指定插入时间或自动递增ID。

If you happen to be running SQL Server with no parallelism and the data is stored in a single file or if the data in the second table fits on one page, then the following will probably work (but no guarantees): 如果您碰巧正在运行没有并行性的SQL Server,并且数据存储在单个文件中,或者第二个表中的数据适合放在一页上,则以下方法可能会起作用(但不能保证):

select au.*
from (select au.Alphabet, min(seqnum) as minseqnum
      from (select au.*, row_number() over (order by (select NULL)) as seqnum
            from AlphabetUsage au
           ) au
      group by au.Alphabet
     ) ausum join
     (select au.*, row_number() over (order by (select NULL)) as seqnum
      from AlphabetUsage au
     ) au
     on ausum.seqnum = au.seqnum

In my experience on SQL Server, row_number() over (order by (select NULL)) assigns a row number without ordering the data. 根据我在SQL Server上的经验, row_number() over (order by (select NULL))分配行号而不对数据进行排序。 However, this is not documented and not guaranteed. 但是,这没有记录并且不能保证。

I highly, highly recommend that you add additional columns to the table, including an identity column to identify each row. 我强烈建议您向表格中添加其他列,包括用于标识每一行的标识列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM