我正在尝试做一些非常简单的事情,在Big Query中变得非常复杂。我想把像人名这样的东西转换成正确的情况(每个单词大写的第一个字母)。
这是我目前正在处理的查询,它几乎可以运行!
SELECT
REGEXP_REPLACE(
CONCAT(
UPPER(LEFT('tESt ing', 1)),
LOWER(SUBSTR('tESt ing', 2))
),
' ([a-z])',
UPPER(' \\1')
);
#outputs: Test ing
#desired output: Test Ing
由于某种原因,UPPER不会处理捕获的组。 如果我把其他文本放入其中它全部变为大写但cap组变量保持小写。
任何帮助都非常感谢。这似乎并不像预期的那样有效(可能是操作顺序......)。无论如何,提前谢谢。
埃里克
答案 0 :(得分:2)
所以我首先尝试了一种费力的但我认为直截了当的方法:
SELECT
CONCAT(
UPPER(LEFT('tESt ing', 1)),
LOWER(REGEXP_EXTRACT(SUBSTR('tESt ing', 2), r'(\w* )')),
UPPER(REGEXP_EXTRACT(SUBSTR('tESt ing', 2), r' (\w)')),
LOWER(REGEXP_EXTRACT(SUBSTR('tESt ing', 2), r' \w(.*)'))
);
似乎有效,并根据需要返回Test Ing
。
然后我尝试了一些简化(我希望)减少工作量:
SELECT
CONCAT(
UPPER(LEFT('tESt ing', 1)),
LOWER(REGEXP_EXTRACT('tESt ing', r'.(\w* )')),
UPPER(REGEXP_EXTRACT('tESt ing', r' (\w)')),
LOWER(REGEXP_EXTRACT('tESt ing', r' \w(.*)'))
);
这也似乎有效(相同的输出)。但是它只删除SUBSTR
次调用 - 而不是我担心的正则表达式操作可能会更昂贵。
仍然认为这可能值得分享。
答案 1 :(得分:1)
我不是百分百肯定,但似乎正则表达式在其中的字符串操作之后得到了评估。
作为替代方案,请尝试SPLIT():
SELECT GROUP_CONCAT(capw, ' ') capitalized_name, FIRST(x) x, id
FROM (
SELECT UPPER(LEFT(w, 1)) + LOWER(SUBSTR(w, 2)) capw, x, POSITION(w) pos, id
FROM (
SELECT SPLIT(x, ' ') w, id
FROM (SELECT 'name lastname' x, 1 id), (SELECT 'name other name' x, 2 id), (SELECT 'a b c' x, 3 id), (SELECT 'name lastname' x, 4 id)
)
ORDER BY pos
)
GROUP BY id
答案 2 :(得分:0)
可以更好地扩展的替代方法 - 您可以在1500万个记录名称数据集上进行测试吗?
SELECT capitalized_name, x, id FROM (
SELECT GROUP_CONCAT(capw, ' ') OVER(PARTITION BY id ORDER BY pos) capitalized_name, x, id, ROW_NUMBER() OVER(PARTITION BY id ORDER BY pos DESC) rn
FROM (
SELECT UPPER(LEFT(w, 1)) + LOWER(SUBSTR(w, 2)) capw, x, POSITION(w) pos, id
FROM (
SELECT SPLIT(rdf_schema_label, ' ') w, rdf_schema_label x, URI id
FROM [dbpedia2014temp.Person]
)
ORDER BY pos
)
) WHERE rn=1
答案 3 :(得分:-1)
REGEX_REPLACE不是MySQL函数,必须实现。 这是一个名为ucwords的函数:
DELIMITER ||
CREATE FUNCTION `ucwords`( str VARCHAR(128) ) RETURNS varchar(128) CHARSET latin1
BEGIN
DECLARE c CHAR(1);
DECLARE s VARCHAR(128);
DECLARE i INT DEFAULT 1;
DECLARE bool INT DEFAULT 1;
DECLARE punct CHAR(17) DEFAULT ' ()[]{},.-_!@;:?/';
SET s = LCASE( str );
WHILE i < LENGTH( str ) DO
BEGIN
SET c = SUBSTRING( s, i, 1 );
IF LOCATE( c, punct ) > 0 THEN
SET bool = 1;
ELSEIF bool=1 THEN
BEGIN
IF c >= 'a' AND c <= 'z' THEN
BEGIN
SET s = CONCAT(LEFT(s,i-1),UCASE(c),SUBSTRING(s,i+1));
SET bool = 0;
END;
ELSEIF c >= '0' AND c <= '9' THEN
SET bool = 0;
END IF;
END;
END IF;
SET i = i+1;
END;
END WHILE;
RETURN s;
END ||
DELIMITER ;
然后你可以使用:来自dual =&gt;的SELECT ucwords('tEst iNg')测试Ing