INDEX+SMALL+IF+ROW函数组合使用解析

1. 【公式解析系列】之条件筛选数组公式的几种经典解法
http://www.exceltip.net/forum.php?mod=viewthread&tid=1889
(出处: Excel 技巧网)

 

2.

[转载]INDEX+SMALL+IF+ROW函数组合使用解析

  (2014-03-08 13:03:09)
标签: 

转载

分类: excel

很多人在Excel中用函数公式做查询的时候,都必然会遇到的一个大问题,那就是一对多的查找/查询公式应该怎么写?大多数人都是从VLOOKUP、INDEX+MATCH中入门的,纵然你把全部的多条件查找方法都学会了而且运用娴熟,如VLOOKUP和&、SUMPRODUCT、LOOKUP(1,0/....,但仍然只能对这种一对多的查询望洋兴叹。

 

这里讲的INDEX+SMALL+IF+ROW的函数组合,就是解决一对多查询的一种通式,如果你能掌握,那在Excel里基本上就没有什么查询你是实现不了的了(除了INDIRECT+RC引用)。

 

下面,我们先来看看示例数据和查询要求:

 

[转载]INDEX+SMALL+IF+ROW函数组合使用解析

由于VLOOKUP、INDEX+MATCH、LOOKUP(1,0/都只是一对一的查询,有的是只查询第一个,有的是只查找最后一个,所以这种组合对于我们这里的要求完全无用武之地。所以,你也别把精力都花在这个上面,虽然也是可以构造出来的,但今天我们要讲的这个组合,是最基本,也是最容易理解的通式,所以请把精力花在这上面。

 

问题1,解答:

=IF(ROW(A1)>COUNTIF($B:$B,"Sam"),"",INDEX(A:A,SMALL(IF($B$2:$B$20="Sam",ROW($2:$20)),ROW(A1))))     [公式一]

 

=IFERROR(INDEX(A:A,SMALL(IF($B$2:$B$20="Sam",ROW($2:$20)),ROW(A1))),"")    [公式二]

 

=INDEX(A:A,SMALL(IF($B$2:$B$20="Sam",ROW($2:$20),4^8),ROW(A1)))&""    [公式三]


 

首先,这三个都是数组公式,什么是“数组公式”呢?数组公式最特殊也最直接的表现,就是你在单元格里输入完公式之后,要按Ctrl+Shift+Enter三键结束,跟“普通公式”只按Enter结束有明显的区别。

为什么有三个公式呢?其实这三个公式的作用和核心是一样的,只是应对不同Excel版本、不同数据类型所用到的屏蔽错误值的手法有所差异而已。

下面我们着重讲讲[公式三],因为这个结构里函数要素最齐全,而组合也是非常符合我们标题所讲到的。

首先我们来简化和分解一下这个公式:

[转载]INDEX+SMALL+IF+ROW函数组合使用解析



从上图我们不难看出,这个组合就是由INDEX作为主体函数,第一参数就是我们要查询并返回的数据区域,第二参数就是由SMALL构造的一个公式,而SMALL构造的函数,无非就是由IF判断生成的一个内存array。

如果你没有函数基础的话,估计还是理解不了,那我们先返回IF结构的计算结果,也就是判断B2:B20区域,如果等于“Sam”,就返回对应的所在行号,不相等的话,就返回4^8,就是4的8次方幂,即65,536,这在xls格式文档中,相当于最大行号,在xlsx格式则不然。

OK,就我们图中的数据,抹黑SMALL函数的array参数,再按F9,不难返回一个内存数组如下:

 

{65536;65536;65536;65536;6;65536;65536;65536;65536;11;65536;13;65536;65536;65536;65536;18;65536;65536}

 

简化一下,我们用“极大”来表示65536,那结果就是:

{ 极大;极大;极大;极大; 6 ;极大;极大;极大;极大; 11 ;极大; 13 ;极大;极大;极大;极大; 18 ;极大;极大 }

这个内存数组也就是这个公式组合里最关键的,你可以看到SMALL函数的第二参数是ROW(A1),这个是返回A1单元格所在的行号,也就是1,当我们整个公式下拉填充之后,就可以得到ROW(A2)、ROW(A3)、ROW(A4)这样的变化,也就是1、2、3、4 …… 这样的自然数序列,从而可以把上面简化了的内存数组里的6、11、13、18给提取出来,因为6是最小值、11是倒数第二小、13是倒数第三小、18是倒数第四小的值,如果还不明白,那请在单元格里输入“=SMALL(”然后按F1查阅SMALL函数的语法和功能说明。

 

6、11、13、18代表什么,我们提取出来有什么用呢?回过头去看看IF函数就明白了,原来这就是那些满足条件的记录所在的行号,这样一来我们就可以把一对多的所有符合条件的记录全都提取出来了。

 

现在回过头来,说说这三个公式都有什么差异和优势?

从上面的分解过程我们也可以看到,其实我们只能凭借下拉公式来得到所有满足条件的所有记录,但具体有多少记录我们不清楚,而且不同的条件返回的记录数量也是不确定的,所以这个公式就决定了我们必须要有容错机制,保证公式下拉之后,不因为返回记录数量的不同而显示多余的0值或者错误值,最常见的如#NUM!。

----------------------------------------------------------

第一个公式比较长,但公式用了一个IF,直接用COUNTIF返回满足条件的记录数量,然后只显示满足条件的记录,公式下拉后其余数量一率用空值表示,而且这里IF函数的False结果可以直接省略以返回FALSE;

第二个公式尤其适用于xlsx格式文档上,直接省略IF的第三参数,因为IFERROR可以涵盖所有错误而不必多费心;

第三个公式只适用在没有特殊格式的数据上,如我们示例数据里的日期、数值,其实都不适合用这个公式,因为我们公式有一个4^8的极大值,而且INDEX函数最后面接了一个&"",其根本目的是为了避免返回65536行里空值通过公式得到0,但这个的间接作用就是将数据直接转化为文本,所以当你要返回的数据里有数值或者日期值,或者其他自定义格式时,就都会被打回原形。。。。

 

 

到此为止,你应该基本上能自己应用了吧?如果还不行,那请重读一遍,熟能生巧嘛~~

下面讲讲第二、第三个问题的公式写法,其实会了第一个,第二个依瓢画葫芦是不成问题的,巧妙的是第三个问题,由于我们本身就是在SMALL的第一参数返回一个内存数组,所以第三个问题才突显这个组合的优势。

这里就只讲公式写法而不展开讨论,公式很容易看明白的,只是内在的机理可能需要先去接触学习一下数组公式的基础内容,才容易深化。

 

 

问题2,解答:

=IFERROR(INDEX(A:A,SMALL(IF($C$2:$C$20%<50,ROW($2:$20)),ROW(A1))),"")

 

=IF(ROW(A1)>COUNTIF($C:$C,"<5000"),"",INDEX(A:A,SMALL(IF($C$2:$C$20<5000,ROW($2:$20)),ROW(A1))))

 

问题3,解答:

=IFERROR(INDEX(A:A,SMALL(IF(MONTH($D$2:$D$20)=3,ROW($2:$20)),ROW(A1))),"")

 

=IF(ROW(A1)>SUMPRODUCT(N(MONTH($D$2:$D$20)=3)),"",INDEX(A:A,SMALL(IF(MONTH($D$2:$D$20)=3,ROW($2:$20)),ROW(A1))))

 

然后,而且必须是数组公式,Ctrl+Shift+Enter三键结束,自己书写公式的时候注意绝对引用与相对引用的适当使用,这又属于基本功咯,请加油。

 

另外这种组合里你可能看到INDEX+SMALL+IF+ROW+COUNTIF,COUNTIF就是用在SMALL函数的第二个参数,这个主要是根据列出的数据的个数,提取第几个的值,对于杂序无指条件的重复值提取,就正好派上用场,具体可以根据自己的使用情况和需求,消化吸收为自己的知识。

 

 

这节课就请专心学习这个,下节课,你可以看看使用MS Query查询能怎么快捷返回相同的结果。

 如何在Excel中根据单元格内容作MS Query查询?】

 

 

数据源示例文件下载:http://pan.baidu.com/share/link?shareid=1325664535&uk=2469898341

 

-------------------------------------

 

Excel难题需要有偿处理的,请点击:

http://excelstudio.taobao.com

 

函数公式写、数据样式转换、数据提取分析、图表制作、VBA代码、SQL查询、网页抓取.....

### Excel 中通过公式定位关键字并获取相同行特定列的值 在 Excel 中,可以通过组合函数实现基于关键字匹配来返回同一行其他列中的值的功能。以下是具体的方法: #### 方法一:使用 `INDEX` 和 `MATCH` 函数 如果目标是从包含关键字的一列中找到对应的另一列的值,则可以利用 `INDEX-MATCH` 组合。 假设: - 数据位于 A 列到 Z 列之间; - 需要在 B 列中查找关键字“全网首发”,并返回该行 C 列的值。 公式如下: ```excel =INDEX(C:C,MATCH("*全网首发*",B:B,0)) ``` 解释: - `MATCH("*全网首发*",B:B,0)` 使用通配符 `*` 来模糊匹配关键字,并返回其所在行号[^1]。 - `INDEX(C:C,...)` 返回对应行号下 C 列的值。 注意:此方法适用于精确匹配或部分匹配的情况。 --- #### 方法二:数组公式的解决方案 当需要处理更复杂的数据集时,可采用数组公式的方式完成多条件筛选。 例如: - 查找关键字“全网首发”所在的行数; - 并返回这一行 D 列的内容。 公式如下(输入完成后需按 Ctrl+Shift+Enter 键确认): ```excel {=INDEX(D:D, SMALL(IF(ISNUMBER(SEARCH("全网首发", B:B)), ROW(B:B)-MIN(ROW(B:B))+1), ROW(A1)))} ``` 说明: - `SEARCH("全网首发", B:B)` 寻找指定字符串的位置[^4]。 - `IF(...)` 过滤符合条件的结果。 - `SMALL(...)` 提取第 N 小的数值,这里用于逐次遍历满足条件的每一行。 - 结果由 `INDEX()` 输出相应位置上的值。 > **提示**: 数组公式可能会影响性能,尤其是针对超大数据表操作时应谨慎应用。 --- #### 方法三:VLOOKUP 的变体形式 虽然 VLOOKUP 主要用于垂直方向上向右查询,但如果调整参数设置也可以间接支持跨列检索。 示例公式: ```excel =VLOOKUP("*全网首发*", B:C, COLUMN(C1)-COLUMN(B1)+1, FALSE) ``` 解析: - `"*全网首发*"` 表达式允许进行模式化搜索[^2]。 - 参数列表定义为范围 `B:C` ,意味着从第二列起算相对偏移量。 - 设置最后一个布尔型标志位为 `FALSE` 实现近似匹配转为精准匹配逻辑转换。 然而需要注意的是,这种方法仅限于右侧扩展字段读取场景并不完全通用。 --- ### 性能优化建议 对于涉及数十万条记录的大规模数据集合而言,单纯依赖内置工作簿级运算可能会显得效率低下甚至崩溃。此时推荐考虑引入外部工具辅助分析或者分批次加载子集逐步解决问题。 另外提醒一点就是务必关闭自动计算选项以减少不必要的资源消耗直到最终调试完毕再重新开启实时更新功能为止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值