2021-01-12

博客介绍了VLOOKUP、COLUMN、MATCH函数的使用方法。当用VLOOKUP查找连续多列数据时,可修改第三个参数;若列数递增,可用COLUMN函数自动化输入参数。实际中需挑选或打乱列顺序时,简单用COLUMN函数无法满足,此时可用MATCH函数返回所需列数。

VLOOKUP、COLUMN、MATCH函数
函数VLOOKUP解析

01
查找数据列顺序一致

用VLOOKUP函数查找多列数据时,如果需要查找的数据列在查找区域中是连续的。那么这时我们只需要修改VLOOKUP的第三个参数,也就是查找数据所在列数就可以完成查找。但是单独地一个一个修改VLOOKUP函数的第三个参数,有时也是很耗时间的。如下图,示例中只有4列也许不觉得时间很久,随着列数的增加浪费的时间将会越多。

如果需要查找的列在原始区域的列数是递增的,我们可以使用COLUMN函数来自动化参数的输入。

我们可以先看看,COLUMN函数的语法及其返回的值。

COLUMN([reference])

我们可以看到COLUMN函数的参数是用方括号表示的,这说明该函数的参数是可以缺省的。就是说我们可以不输入参数值。COLUMN 函数返回给定 单元格引用 的列号。 例如,在B列任意单元格公式=COLUMN ()返回2,因为B列的列号是2。

那么我们将COLUMN函数向右拖动将分别生成2、3、4、5.刚好是我们VLOOKUP需要的第三个参数。

所以结合相对引用可以将上述B9中单元格的公式改为:

=VLOOKUP($A9,9,9,A2:2:2:E$6,COLUMN(),FALSE)

然后往右拖动填充公式就可以一次性完成数据查找了。是不是超快捷?

这里切换绝对引用使用了快捷键 F4。

02
查找数据列顺序不一致

上面的例子是理想情况下的,实际情况是很多时候我们需要查找的数据是从原数据区域中挑选几列,甚至会将原来的列顺序打乱。虽然这种情况下,需要做的也是修改第三个参数的数值,但是简单的使用COLUMN函数却无法满足需求,因为第三参数并不是递增的。这时我们需要用的MATCH函数。

在这里插入图片描述

MATCH的英文名称是匹配。所以顾名思义,使用 MATCH 函数在指定单元格区域内中搜索匹配的项,然后返回该项在此区域中的相对位置。

MATCH(lookup_value, lookup_array, [match_type])

例如,在B8中输入公式 =MATCH(B8,A1:E1,0)返回数字 2,因为物品是该区域中(标题行中)的第二项。

以此类推,可以快速返回其他标题所在的列数。返回的结果正是我们VLOOKUP需要的第三个参数。所以B9中单元格的公式可以改为:

=VLOOKUP($A9,9,9,A2:2:2:E6,MATCH(B8,6,MATCH(B8,6,MATCH(B8,A1:1:1:E$1,0))

接下来只需要拖动公式填充就可以快速查找需要的数据了。
<think>好的,我现在需要解决用户的问题,关于如何将SQLite数据库中的日期字段从'2021/1/12'格式转换为'2021-01-12'。首先,我需要回顾用户之前的提问和我的回答,确保解决方案的一致性。 用户之前提到日期显示为1899-12-30的问题,主要是因为存储格式不正确或者转换错误。现在的问题是日期格式需要统一为ISO8601标准,即YYYY-MM-DD。根据引用[3],SQLite提供了日期函数如strftime来处理格式转换,这可能对当前问题有帮助。 首先,我需要确认用户的数据存储类型。根据之前的回答,SQLite使用类型亲缘性(引用[5]),日期可能存储为TEXT。如果字段是TEXT类型,那么直接处理字符串即可。但用户现在的日期格式是'2021/1/12',即月份和日为单数字,需要转换为双数字格式。 接下来,我需要考虑如何分割原始字符串并重新组合。用户给出的示例日期是'2021/1/12',可能还有其他类似的情况,比如'2021/12/1',所以需要处理不同部分的长度。可以使用substr函数来提取年、月、日,然后使用printf或CASE语句来补零。 引用[2]中提到的datetime函数可能不适用,因为用户的数据是文本格式,需要先转换为正确的日期格式。或者,可以先将字符串分割,再重新格式化为标准格式。 另外,要注意原始数据中是否存在不同的分隔符或格式,例如是否有日期是'2021-1-12'或者其他变体。需要确保SQL语句能够处理所有情况。 步骤可能包括: 1. 使用substr提取年、月、日部分。 2. 检查月和日的长度,如果为1位,前面补零。 3. 组合成YYYY-MM-DD格式。 4. 执行UPDATE语句来修改表中的数据。 需要注意的是,如果字段中存在其他格式的日期,如'2022/10/5',也需要正确处理。可能需要更灵活的处理方式,例如使用INSTR查找分隔符的位置,或者使用REPLACE函数替换斜杠为横杠,但这样可能无法处理单数字月份和日期的情况。 因此,最佳方法可能是分割字符串,并分别处理月、日的补零。例如,使用SUBSTR和INSTR来找到斜杠的位置,从而确定各部分的位置。然后,使用printf('%02d', month)来补零。 不过,SQLite的字符串处理函数有限,可能需要嵌套多个SUBSTR和INSTR来定位。例如: UPDATE表 SET date_field = printf('%04d-%02d-%02d', SUBSTR(date_field, 1, 4), CASE WHEN LENGTH(SUBSTR(date_field, INSTR(date_field, '/')+1, INSTR(SUBSTR(date_field, INSTR(date_field, '/')+1), '/')-1)) = 1 THEN '0' || SUBSTR(...) ELSE SUBSTR(...) END, ...); 这可能会比较复杂,需要多次定位斜杠的位置。或者,如果日期格式统一为YYYY/MM/DD或YYYY/M/D,可以分三次分割。 另一种方法是使用REPLACE将斜杠替换为横杠,然后使用strftime重新格式化,但需要确保月和日已经是两位数。不过,如果原数据中的月份和日是单数字,直接替换斜杠并不能补零,所以必须处理这部分。 例如,将'2021/1/12'转换为'2021-01-12',需要将月份补零。可以先用SUBSTR和INSTR分割各部分,然后分别处理月和日。 可能需要这样的步骤: - 第一个斜杠的位置:pos1 = INSTR(date_field, '/') - 年份:SUBSTR(date_field, 1, pos1-1) - 剩余部分:SUBSTR(date_field, pos1+1) - 第二个斜杠的位置:pos2 = INSTR(剩余部分, '/') - 月份:SUBSTR(剩余部分, 1, pos2-1) - 日:SUBSTR(剩余部分, pos2+1) 然后,对月份和日分别补零,使用printf('%02d', month)或者CASE WHEN LENGTH(month)=1 THEN '0' || month ELSE month END。 但SQLite中可能没有INSTR函数,或者不同版本的SQLite支持不同。根据引用[3],SQLite支持strftime,但字符串处理函数可能有限。例如,INSTR可能不可用,需要查找替代方法。 查阅SQLite的字符串函数,发现SQLite有instr函数,语法为instr(string, substring),返回子字符串的位置。例如,INSTR('2021/1/12', '/') 返回5。因此,可以定位第一个斜杠的位置,然后提取年份,剩下的部分再次分割月份和日。 例如: UPDATE expert SET date_field = printf( '%s-%02d-%02d', SUBSTR(date_field, 1, INSTR(date_field, '/') - 1), SUBSTR( SUBSTR(date_field, INSTR(date_field, '/') + 1), 1, INSTR(SUBSTR(date_field, INSTR(date_field, '/') + 1), '/') - 1 ), SUBSTR( SUBSTR(date_field, INSTR(date_field, '/') + 1), INSTR(SUBSTR(date_field, INSTR(date_field, '/') + 1), '/') + 1 ) ) WHERE date_field LIKE '%/%/%'; 但这里的问题是如何处理月份和日的数值转换,因为SUBSTR返回的是字符串,需要用CAST转为整数,然后再用printf的%02d格式来补零。例如: SUBSTR部分得到月份为'1',然后CAST('1' AS INTEGER)得到1,printf('%02d', 1)得到'01'。因此,可能需要将SUBSTR的部分转换为整数,再格式化。 因此,完整的UPDATE语句可能如下: UPDATE expert SET date_field = printf( '%s-%02d-%02d', SUBSTR(date_field, 1, INSTR(date_field, '/') - 1), CAST(SUBSTR( SUBSTR(date_field, INSTR(date_field, '/') + 1), 1, INSTR(SUBSTR(date_field, INSTR(date_field, '/') + 1), '/') - 1 ) AS INTEGER), CAST(SUBSTR( SUBSTR(date_field, INSTR(date_field, '/') + 1), INSTR(SUBSTR(date_field, INSTR(date_field, '/') + 1), '/') + 1 ) AS INTEGER) ) WHERE date_field LIKE '%/%/%'; 这个语句的作用是,将日期字段中的'YYYY/MM/DD'或'YYYY/M/D'转换为'YYYY-MM-DD',并补零月份和日。 但是,需要测试该语句是否适用于不同的情况,例如: - '2021/1/12' → '2021-01-12' - '2022/10/5' → '2022-10-05' - '2023/3/9' → '2023-03-09' 另外,需要确保WHERE子句正确筛选出需要转换的日期格式,避免误改其他格式的数据。例如,使用LIKE '%/%/%'来匹配包含两个斜杠的日期。 另外,需要考虑原始数据是否有其他分隔符或格式,例如是否有可能存在三个斜杠的情况,或者年份不是四位的情况,但用户的问题中明确给出的是'2021/1/12'转换为'2021-01-12',所以假设日期格式为YYYY/M/D或YYYY/MM/DD,其中月和日可能为1或2位数字。 此外,执行UPDATE之前,最好先备份数据,或者在测试环境中验证语句的正确性。 总结步骤: 1. 使用INSTR定位斜杠位置,分割年、月、日。 2. 将月和日转换为整数,再使用printf补零为两位。 3. 组合成YYYY-MM-DD格式。 4. 更新符合条件的记录。 需要注意的是,SQLite的日期函数如strftime可能无法直接解析非标准格式,因此需要手动处理字符串。这种方法适用于已知格式的转换,但可能不适用于混合格式的情况。 最后,根据用户提供的引用[3],使用strftime函数可能更简洁,但需要先将字符串转换为合法的日期格式。例如,如果原始日期是'2021/1/12',可以尝试使用substr和替换来构造一个能被SQLite识别的格式,然后使用strftime重新格式化。例如: UPDATE expert SET date_field = strftime('%Y-%m-%d', substr(date_field, 1, 4) || '-' || substr('0' || substr(date_field, 6, instr(substr(date_field, 6), '/') - 1), -2) || '-' || substr('0' || substr(date_field, instr(date_field, '/', 1, 2) + 1), -2) ) WHERE date_field LIKE '%/%/%'; 这里,假设第一个斜杠在位置5(年份后),第二个斜杠在月份后。但可能需要更复杂的处理。例如,将'2021/1/12'转换为'2021-01-12',需要提取月份和日并补零。这种方法可能更高效,但需要确保字符串分割正确。 总的来说,用户的问题需要将'YYYY/M/D'转换为'YYYY-MM-DD',使用字符串分割和格式化补零是最直接的方法。需要确保SQL语句正确处理不同长度的月份和日,并在转换后进行验证。</think>#### 一、问题分析与解决方案选择 该需求属于**非标准日期格式标准化**问题,核心是通过SQL字符串操作将`YYYY/M/D`格式转换为`YYYY-MM-DD`。根据SQLite的字符串处理函数特性,推荐使用`SUBSTR`+`INSTR`组合定位分隔符,配合`printf`补零实现[^3][^5]。 #### 二、完整转换SQL语句 ```sql -- 单次操作完成格式转换 UPDATE expert SET date_field = printf('%04d-%02d-%02d', CAST(SUBSTR(date_field, 1, pos1-1) AS INTEGER), -- 年 CAST(SUBSTR(remain_part1, 1, pos2-1) AS INTEGER), -- 月 CAST(SUBSTR(remain_part1, pos2+1) AS INTEGER) -- 日 ) FROM ( SELECT id, INSTR(date_field, '/') AS pos1, -- 第一个斜杠位置 SUBSTR(date_field, INSTR(date_field, '/')+1) AS remain_part1, -- 剩余部分 INSTR(SUBSTR(date_field, INSTR(date_field, '/')+1), '/') AS pos2 -- 第二个斜杠位置 FROM expert WHERE date_field LIKE '%/%/%' -- 仅处理含两个斜杠的日期 ) AS subquery WHERE expert.id = subquery.id; ``` #### 三、操作分解说明 1. **定位分隔符位置** - `INSTR(date_field, '/')`获取第一个斜杠位置 - 对剩余字符串再次执行`INSTR`获取第二个斜杠位置 2. **分段提取日期组件** ```sql SUBSTR(date_field, 1, pos1-1) -- 提取年份(YYYY) SUBSTR(remain_part1, 1, pos2-1) -- 提取月份(M) SUBSTR(remain_part1, pos2+1) -- 提取日(D) ``` 3. **标准化数字格式** 通过`CAST(... AS INTEGER)`清除前导零(若存在),再使用`printf`强制补零: ```sql printf('%04d-%02d-%02d', year, month, day) -- 输出YYYY-MM-DD格式 ``` #### 四、验证与异常处理 ```sql -- 检查转换结果 SELECT date_field FROM expert WHERE date_field NOT GLOB '????-??-??*'; -- 查找未转换成功的记录 -- 处理特殊格式(如单年份) UPDATE expert SET date_field = NULL WHERE date_field NOT LIKE '%/%/%'; -- 非目标格式设为空 ``` #### 五、性能优化建议 1. **添加临时索引** ```sql CREATE INDEX tmp_idx ON expert(date_field); -- 执行转换操作 DROP INDEX tmp_idx; ``` 2. **分批次更新** ```sql UPDATE expert SET date_field = (...) WHERE id BETWEEN 1 AND 10000; -- 分片更新 ``` #### 六、预防措施 ```sql -- 创建新表约束格式 CREATE TABLE expert_new ( id INTEGER PRIMARY KEY, event_date TEXT CHECK( event_date GLOB '????-??-??*' OR event_date IS NULL ) ); -- 迁移数据 INSERT INTO expert_new SELECT id, date_field FROM expert; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值