Cuando necesitas los tres primeros digitos de un codigo o los cuatro ultimos de un telefono, recurrir a un SUBSTRING verboso es excesivo. PostgreSQL ofrece dos funciones cortas: LEFT toma caracteres desde el inicio de la cadena y RIGHT los toma desde el final. Veamoslas en la practica y de paso descubramos sus bordes afilados.
Sintaxis basica
Ambas funciones reciben una cadena y un numero de caracteres: LEFT(string, n) y RIGHT(string, n). Cuentan caracteres, no bytes, asi que UTF-8 no da problemas.
SELECT LEFT('PROMO-2026', 5) AS head,
RIGHT('PROMO-2026', 4) AS tail;
Sobre una tabla real esto es comodo para extraer prefijos y sufijos. Supongamos que orders.status guarda una cadena como paid-eu y queremos las primeras letras del estado:
SELECT id,
LEFT(status, 4) AS status_head
FROM orders
LIMIT 5;
Propiedades clave:
- El tipo del resultado es
text.
- Si
n es mayor que la longitud de la cadena, recuperas la cadena entera, sin error y sin relleno.
- Una entrada
NULL produce una salida NULL.
Enmascarar un numero de tarjeta
El caso clasico es mostrar solo los cuatro ultimos digitos de una tarjeta de pago y ocultar el resto. Aqui RIGHT es justo la herramienta:
SELECT RIGHT('4111111111114242', 4) AS last4;
Para obtener el formato habitual **** 4242, concatena una mascara con la cola. Supongamos que hay una columna con el numero de tarjeta del usuario:
SELECT u.id,
'**** ' || RIGHT(card_number, 4) AS masked_card
FROM users u
JOIN payment_methods pm ON pm.user_id = u.id;
Del mismo modo, LEFT ayuda a extraer el BIN, los seis primeros digitos que identifican al banco emisor:
SELECT LEFT(card_number, 6) AS bin
FROM payment_methods;
Gotcha: LEFT y RIGHT cortan caracteres, no partes "logicas". Si el numero tiene espacios o guiones (4111 1111 1111 4242), RIGHT(..., 4) devuelve 4242 solo si la cola esta limpia. Elimina primero los separadores con REPLACE o podrias mostrar por accidente un espacio en lugar de un digito.
Longitud negativa
Esta es la opcion mas infravalorada. Si pasas un n negativo, PostgreSQL cuenta caracteres desde el extremo opuesto y devuelve el resto.
LEFT(s, -k) devuelve la cadena sin sus ultimos k caracteres.
RIGHT(s, -k) devuelve la cadena sin sus primeros k caracteres.
SELECT LEFT('order-12345', -5) AS without_tail,
RIGHT('order-12345', -6) AS without_head;
Esto brilla cuando conoces la longitud de la parte que vas a recortar pero no la de la cadena. Por ejemplo, quitar un sufijo de dominio fijo o eliminar un prefijo conocido. Pero ten cuidado: si -k es mayor en magnitud que la longitud de la cadena, obtienes una cadena vacia '', no NULL, asi que es facil perder datos en silencio.
LEFT y RIGHT frente a SUBSTRING
SUBSTRING es mas potente pero mas verboso. Cualquier LEFT/RIGHT puede expresarse con el:
SELECT SUBSTRING(name FROM 1 FOR 3) FROM users;
SELECT SUBSTRING(name FROM length(name) - 3 + 1) FROM users;
Fijate en que el equivalente de RIGHT te obliga a calcular length() a mano y facilita errores de uno en uno. Asi que la regla es simple:
- Necesitas un prefijo o sufijo fijo: usa
LEFT o RIGHT, el codigo se lee al instante.
- Necesitas un trozo del medio o una posicion dinamica: usa
SUBSTRING.
- Necesitas recortar por un patron y no por longitud: mira hacia
split_part o las expresiones regulares.
Un ejemplo realista: agrupar empleados por la primera letra de su departamento con LEFT, mucho mas limpio que SUBSTRING:
SELECT LEFT(dept, 1) AS dept_initial,
count(*) AS people
FROM employees
GROUP BY LEFT(dept, 1)
ORDER BY dept_initial;
MySQL y ClickHouse
Buena noticia: LEFT y RIGHT existen en MySQL con la misma sintaxis LEFT(str, len) y RIGHT(str, len), asi que las consultas se trasladan casi sin cambios.
- MySQL no admite longitud negativa:
LEFT('abc', -1) devuelve una cadena vacia, no "todo salvo el ultimo caracter". Esta es la diferencia principal al migrar.
- ClickHouse tambien tiene
left y right; un argumento negativo ahi funciona como en PostgreSQL, contando desde el final.
- En MySQL ambas funciones cuentan caracteres segun el juego de caracteres actual de la columna, lo que suele coincidir con el comportamiento de PostgreSQL para UTF-8.
SELECT LEFT(email, 3) AS prefix,
RIGHT(email, 3) AS suffix
FROM users;
En resumen: LEFT y RIGHT son la forma mas rapida de tomar el borde de una cadena. Recuerda la longitud negativa como "recortar por el otro extremo", limpia siempre los separadores antes de enmascarar y ten presente que el argumento negativo no funciona en MySQL.
Cuando necesitas los tres primeros digitos de un codigo o los cuatro ultimos de un telefono, recurrir a un
SUBSTRINGverboso es excesivo. PostgreSQL ofrece dos funciones cortas:LEFTtoma caracteres desde el inicio de la cadena yRIGHTlos toma desde el final. Veamoslas en la practica y de paso descubramos sus bordes afilados.Sintaxis basica
Ambas funciones reciben una cadena y un numero de caracteres:
LEFT(string, n)yRIGHT(string, n). Cuentan caracteres, no bytes, asi que UTF-8 no da problemas.SELECT LEFT('PROMO-2026', 5) AS head, -- 'PROMO' RIGHT('PROMO-2026', 4) AS tail; -- '2026'Sobre una tabla real esto es comodo para extraer prefijos y sufijos. Supongamos que
orders.statusguarda una cadena comopaid-euy queremos las primeras letras del estado:SELECT id, LEFT(status, 4) AS status_head FROM orders LIMIT 5;Propiedades clave:
text.nes mayor que la longitud de la cadena, recuperas la cadena entera, sin error y sin relleno.NULLproduce una salidaNULL.Enmascarar un numero de tarjeta
El caso clasico es mostrar solo los cuatro ultimos digitos de una tarjeta de pago y ocultar el resto. Aqui
RIGHTes justo la herramienta:SELECT RIGHT('4111111111114242', 4) AS last4; -- '4242'Para obtener el formato habitual
**** 4242, concatena una mascara con la cola. Supongamos que hay una columna con el numero de tarjeta del usuario:SELECT u.id, '**** ' || RIGHT(card_number, 4) AS masked_card FROM users u JOIN payment_methods pm ON pm.user_id = u.id;Del mismo modo,
LEFTayuda a extraer el BIN, los seis primeros digitos que identifican al banco emisor:SELECT LEFT(card_number, 6) AS bin FROM payment_methods;Gotcha:
LEFTyRIGHTcortan caracteres, no partes "logicas". Si el numero tiene espacios o guiones (4111 1111 1111 4242),RIGHT(..., 4)devuelve4242solo si la cola esta limpia. Elimina primero los separadores conREPLACEo podrias mostrar por accidente un espacio en lugar de un digito.Longitud negativa
Esta es la opcion mas infravalorada. Si pasas un
nnegativo, PostgreSQL cuenta caracteres desde el extremo opuesto y devuelve el resto.LEFT(s, -k)devuelve la cadena sin sus ultimoskcaracteres.RIGHT(s, -k)devuelve la cadena sin sus primeroskcaracteres.SELECT LEFT('order-12345', -5) AS without_tail, -- 'order-' RIGHT('order-12345', -6) AS without_head; -- '12345'Esto brilla cuando conoces la longitud de la parte que vas a recortar pero no la de la cadena. Por ejemplo, quitar un sufijo de dominio fijo o eliminar un prefijo conocido. Pero ten cuidado: si
-kes mayor en magnitud que la longitud de la cadena, obtienes una cadena vacia'', noNULL, asi que es facil perder datos en silencio.LEFT y RIGHT frente a SUBSTRING
SUBSTRINGes mas potente pero mas verboso. CualquierLEFT/RIGHTpuede expresarse con el:-- LEFT(name, 3) is equivalent to: SELECT SUBSTRING(name FROM 1 FOR 3) FROM users; -- RIGHT(name, 3) is equivalent to: SELECT SUBSTRING(name FROM length(name) - 3 + 1) FROM users;Fijate en que el equivalente de
RIGHTte obliga a calcularlength()a mano y facilita errores de uno en uno. Asi que la regla es simple:LEFToRIGHT, el codigo se lee al instante.SUBSTRING.split_parto las expresiones regulares.Un ejemplo realista: agrupar empleados por la primera letra de su departamento con
LEFT, mucho mas limpio queSUBSTRING:SELECT LEFT(dept, 1) AS dept_initial, count(*) AS people FROM employees GROUP BY LEFT(dept, 1) ORDER BY dept_initial;MySQL y ClickHouse
Buena noticia:
LEFTyRIGHTexisten en MySQL con la misma sintaxisLEFT(str, len)yRIGHT(str, len), asi que las consultas se trasladan casi sin cambios.LEFT('abc', -1)devuelve una cadena vacia, no "todo salvo el ultimo caracter". Esta es la diferencia principal al migrar.leftyright; un argumento negativo ahi funciona como en PostgreSQL, contando desde el final.-- Works identically in PostgreSQL and MySQL SELECT LEFT(email, 3) AS prefix, RIGHT(email, 3) AS suffix FROM users;En resumen:
LEFTyRIGHTson la forma mas rapida de tomar el borde de una cadena. Recuerda la longitud negativa como "recortar por el otro extremo", limpia siempre los separadores antes de enmascarar y ten presente que el argumento negativo no funciona en MySQL.