* FROM users; SELECT
Prueba Tecnica
SQL TEST
Preguntas
Dadas las siguientes tablas:
Y
* FROM loan_details; SELECT
Escribe una consulta que de la lista de usuarios que pidieron un préstamo más de una vez en el mismo día, agrupado por usuario y tipo de préstamo. Ordenado de mayor a menor por fecha de creación del préstamo.
Respuesta
Para este ejercicio me tomé la libertad de crear una BD de muestra con las tablas correspondientes:
users (
create table
user_id int primary key,varchar(50)
username
);
-- Insertar datos en users
users (user_id, username) values
insert into 1, 'John Doe'),
(2, 'Jane Don'),
(3, 'Alice Jones'),
(4, 'Lisa Romero');
(
## Crear tabla loan_details con una clave foránea a users
loan_details (
create table
user_loan_id int primary key,
user_id int,
loan_type int,
loan_date date,key (user_id) references users(user_id)
foreign
);
## Insertar datos en loan_details
loan_details (user_loan_id, user_id, loan_type, loan_date) values
insert into 1, 1, 1, '2023-08-02'),
(2, 2, 1, '2023-08-03'),
(3, 3, 2, '2023-08-02'),
(4, 4, 2, '2023-08-04'),
(5, 2, 2, '2023-08-03'),
(6, 1, 1, '2023-08-02'),
(7, 3, 2, '2023-08-04'),
(8, 4, 3, '2023-08-03'),
(9, 1, 4, '2023-08-03'),
(10, 3, 1, '2023-08-02'),
(11, 4, 2, '2023-08-04'),
(12, 3, 2, '2023-08-02'),
(13, 1, 1, '2023-08-02'),
(14, 4, 3, '2023-08-03'); (
Resultando en:
## Consulta
select users.username, ld.loan_type tipo_prestamo, ld.loan_date fecha_prestamo,count(*) Cantidad_prestamos
from loan_details ld = users.user_id
left join users on ld.user_id
group by users.username, ld.loan_type, ld.loan_datecount(*) > 1
having order by ld.loan_date desc
username | tipo_prestamo | fecha_prestamo | Cantidad_prestamos |
---|---|---|---|
Lisa Romero | 2 | 2023-08-04 | 2 |
Lisa Romero | 3 | 2023-08-03 | 2 |
John Doe | 1 | 2023-08-02 | 3 |
Alice Jones | 2 | 2023-08-02 | 2 |
Dada la siguiente tabla:
* FROM transactions; SELECT
Crea una consulta que genere el monto promedio y total mensual de transacciones SETTLED. Por categoría junto con el monto acumulado mes a mes.
Respuesta
Al igual que en el caso anterior, armé la tabla en una BD de prueba:
transactions (
create table
transaction_date date,varchar(50),
state varchar(50),
category decimal(10, 2)
amount
);
transactions (transaction_date, state, category, amount) values
insert into '2023-08-07', 'SETTLED', 'CREDIT_CARD', -1044.33),
('2023-08-21', 'SETTLED', 'CREDIT_CARD', -1178.55),
('2023-09-04', 'CANCELED', 'CHECKING', -20.00),
('2023-09-04', 'SETTLED', 'CHECKING', -1449.75),
('2023-10-02', 'SETTLED', 'CHECKING', -12530.39),
('2023-10-09', 'SETTLED', 'CHECKING', -1815.89),
('2023-10-16', 'SETTLED', 'CHECKING', -1863.37),
('2023-10-23', 'SETTLED', 'CHECKING', -9275.68),
('2023-10-30', 'CANCELED', 'CHECKING', -40.00),
('2023-10-30', 'SETTLED', 'CHECKING', -6223.13),
('2023-11-06', 'CANCELED', 'CHECKING', -658.09),
('2023-11-06', 'SETTLED', 'CHECKING', -12602.32),
('2023-11-13', 'CANCELED', 'CHECKING', -84.45),
('2023-11-13', 'SETTLED', 'CHECKING', -8090.13),
('2023-11-20', 'CANCELED', 'CHECKING', -20.00),
('2023-11-20', 'SETTLED', 'CHECKING', -3187.59),
('2023-11-20', 'SETTLED', 'CREDIT_CARD', -2563.17),
('2023-11-27', 'CANCELED', 'CHECKING', -194.81),
('2023-11-27', 'SETTLED', 'CHECKING', -10376.22),
('2023-11-27', 'SETTLED', 'CREDIT_CARD', -4117.82),
('2023-12-04', 'SETTLED', 'CHECKING', -3579.06),
('2023-12-04', 'SETTLED', 'CREDIT_CARD', -6917.86),
('2023-12-11', 'CANCELED', 'CHECKING', -239.85),
('2023-12-11', 'SETTLED', 'CHECKING', 0.00),
('2023-12-11', 'SETTLED', 'CREDIT_CARD', -6223.47),
('2023-12-18', 'CANCELED', 'CHECKING', -199.96),
('2023-12-18', 'CANCELED', 'CREDIT_CARD', -371.89),
('2023-12-18', 'SETTLED', 'CHECKING', -3988.03),
('2023-12-18', 'SETTLED', 'CREDIT_CARD', -7955.47),
('2023-12-25', 'AUTHORIZED', 'CREDIT_CARD', -20.00),
('2023-12-25', 'CANCELED', 'CHECKING', -20.00),
('2023-12-25', 'CANCELED', 'CREDIT_CARD', -320.24),
('2023-12-25', 'SETTLED', 'CHECKING', -5773.02),
('2023-12-25', 'SETTLED', 'CREDIT_CARD', -5404.81),
('2024-01-01', 'CANCELED', 'CREDIT_CARD', -157.46),
('2024-01-01', 'SETTLED', 'CHECKING', -8633.34),
('2024-01-08', 'CANCELED', 'CREDIT_CARD', -959.71),
('2024-01-08', 'SETTLED', 'CHECKING', -2676.16),
('2024-01-15', 'SETTLED', 'CHECKING', -1662.51),
('2024-01-15', 'SETTLED', 'CREDIT_CARD', -1095.59),
('2024-01-22', 'SETTLED', 'CREDIT_CARD', -784.72); (
Y la consulta:
as (
with transacciones_mensuales date(date_format(transaction_date, '%Y-%m-01')) fecha,
select avg(amount) monto_promedio,
sum(amount) monto_total_mensual
from transactionsstate = "SETTLED"
where date(date_format(transaction_date, '%Y-%m-01'))
group by
)
select
fecha,
monto_promedio,
monto_total_mensual,sum(monto_total_mensual) over (order by fecha
rows between unbounded preceding and current row) acumulado_mensual from transacciones_mensuales
Resultando en:
fecha | monto_promedio | monto_total_mensual | acumulado_mensual |
---|---|---|---|
2023-08-01 | -1111.44 | -2222.88 | -2222.88 |
2023-09-01 | -1449.75 | -1449.75 | -3672.63 |
2023-10-01 | -6341.692 | -31708.46 | -35381.09 |
2023-11-01 | -6822.875 | -40937.25 | -76318.34 |
2023-12-01 | -4980.215 | -39841.72 | -116160.06 |
2024-01-01 | -2970.464 | -14852.32 | -131012.38 |
BI TEST: Grafico
Uno de los productos de Rabbit llamado producto R permite a los tenderos (dueños de una tienda) la posibilidad de recibir pago de servicios y realizar recargas de tiempo aire a los usuarios finales. Cada transacción genera un ingreso para Rabbit equivalente al 1% del monto total transaccionado o de la recarga de tiempo aire. Cada tendero que activa el uso del producto R implica una inversión para Rabbit que puede variar de acuerdo con el mes. La relación entre este costo de colocación individual y el mes de activación del producto se encuentra en el archivo cac.csv.
Para el objetivo de este ejercicio se requieren las siguientes definiciones:
Tendero: Dueño de una tienda
Revenue: Monto total que ha sido obtenido por los ingresos que genera el producto R para Rabbit acumulados hasta cierto mes.
Retorno de la inversión: es igual al revenue acumulado hasta cierto mes menos la inversión original y el resultado de esta resta dividido entre la inversión original. (revenue-inversión original)/inversión original
El ingreso se calcula como el monto de la transacción multiplicado por 0.01; es decir, cada transacción genera 1% de ingreso para Rabbit con respecto del monto total transaccionado.
Solo las transacciones con status: “SUCCESSFUL” son válidas para generar ingresos.
La inversión original se calcula como el número de clientes que fueron activados en un mes en particular multiplicado por el costo de colocación individual de dicho mes.
Cosecha: Periodos en los que se han realizado activaciones del producto R. Estos periodos se agrupan por mes y año en formato “YYYY-MM”
No todos los tenderos que se activan en el producto R terminan realizando transacciones a clientes finales.
Con base en la información descrita anteriormente responde los siguientes puntos mediante Python o R project y adjunta tu código o notebook en el cuerpo del correo que contiene este documento.
Crear una gráfica que muestre el retorno de la inversión que ha generado cada una de las cosechas del producto R en cada uno de los meses subsecuentes a la originación de la cosecha. Es decir; que porcentaje de la inversión se ha recuperado para cada cosecha al mes 0, al mes 1 al mes 2, etc tras haber sido colocada. Mes cero es el mes de originación de la cosecha ya que los clientes regularmente empiezan a transaccionar el mismo día que activan el producto R.
Identificar cuál sería el precio máximo permitido de costo de colocación individual para lograr recuperar la inversión original en menos de 3 meses. Para ello crear un promedio ponderado de comportamiento general de todas las cosechas.
Respuesta
library(dplyr, warn = FALSE)
library(tidyr)
library(jsonlite)
library(lubridate)
library(echarts4r)
# Carga de datos
<- vroom::vroom("activations.csv")
activations <- vroom::vroom("cac.csv")
cac <- readxl::read_excel("transactions.xlsx")
transactions
# Arreglo en los datos de transacciones
<-
transactions |>
transactions mutate(
transactionHistory = gsub("\\'", "\"", transactionHistory),
transactionHistory = lapply(transactionHistory, jsonlite::fromJSON)
|>
) ::unnest(transactionHistory) |>
tidyrmutate(
transactionAmount = as.numeric(gsub("\\$", "", transactionAmount))
)
<-
cac |>
cac mutate(
costPerActivation = as.numeric(gsub("\\$", "", costPerActivation)),
cohort = as_date(zoo::as.yearmon(cohort, format = "%Y-%m"))
)
<-
activations |>
activations mutate(
activationAt = floor_date(activationAt, "month")
)
Ahora, vamos a trabajar los datos:
<-
transactions |>
transactions select(!transactionId) |>
filter(status == "SUCCESSFUL") |>
mutate(
revenue = transactionAmount*.01,
date = floor_date(as_date(date), "month")) |>
left_join(
activations,by = c("customerId" = "customerId")) |>
group_by(date, activationAt) |>
summarise(
revenue = sum(revenue, na.rm = T),
clientes = n_distinct(customerId)
|>
) group_by(activationAt) |>
arrange(date) |>
mutate(cumulative_revenue = cumsum(revenue)) |>
arrange(activationAt) |>
left_join(
cac,by = c("activationAt" = "cohort")
|>
) replace_na(list(costPerActivation = 0)) |>
mutate(costo_total = costPerActivation*clientes,
retorno_de_inversion = (cumulative_revenue-
/costo_total,
costo_total)mes = as.character(row_number()-1))
`summarise()` has grouped output by 'date'. You can override using the
`.groups` argument.
GRAFICO
|>
transactions e_charts(mes) |>
e_line(retorno_de_inversion, symbol = "none") |>
e_tooltip(trigger = "axis", backgroundColor = "#fff") |>
e_theme("infographic") |>
e_title(
"CAC recovery by enrollment Cohort",
left = "center"
|>
) e_legend(right = 0,
orient = "vertical")
CALCULO DE VALOR MAXIMO
# Filtro final para obtener el promedio de retornos de inversion y
# costo de activación individual
<-
calculo |>
transactions filter(
<= 3
mes |>
) group_by(
activationAt|>
) summarise(
ret_inv = mean(retorno_de_inversion, na.rm = T)
|>
) filter(!is.infinite(ret_inv)) |>
left_join(
cac,by = c("activationAt" = "cohort")
)
# Regresion lineal para calcular la correlacion entre el costo inicial
# y el retorno de inversion
<-
model summary(
lm(calculo$ret_inv ~ calculo$costPerActivation)
)
# Ponderacion final
$coefficients[[1]]/abs(model$coefficients[[2]]) model
[1] 31.44717