3

我正在尝试做一些在 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 组变量保持小写。

任何帮助都非常感谢。这似乎很奇怪,这不能按预期工作(也许是操作顺序......)。无论如何,提前谢谢。

埃里克

4

4 回答 4

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调用——而不是我担心可能更昂贵的正则表达式操作。

不过,认为这可能值得分享。

于 2015-01-30T02:12:43.983 回答
1

I'm not 100% sure, but it seems the regular expression gets evaluated after the string operations within it.

As an alternative, try 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

enter image description here

于 2015-01-27T02:40:59.793 回答
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
于 2015-01-27T08:03:48.430 回答
-3

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 ;

然后你可以使用: SELECT ucwords('tEst iNg') from dual => Test Ing

于 2015-01-28T11:39:42.573 回答