es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Precio de la acción inferior a cierto valor durante 6 días hábiles consecutivos o más en el último mes.

Este es para la base de datos de MySQL 8.X.

Mis requisitos son los siguientes:
Si el precio de una acción es inferior a un valor determinado durante 6 días consecutivos o más en el último mes, entonces necesito informar al inversor.

No habrá ningún precio de acción en días festivos ni fines de semana. Por lo tanto, no habrá datos para estos días.

Por ejemplo:
En los datos a continuación, el precio de la acción es inferior a 100 durante 6 días consecutivos entre el 14 y el 21 de diciembre de 2021. Necesito encontrar dichas acciones y el número de días en los que el precio de la acción ha bajado por debajo del valor objetivo.

fecha_efectiva seguridad precio_mercado
1-dic-2021 NOMBREACCIÓN 99
2-dic-2021 NOMBREACCIÓN 98
3-dic-2021 NOMBREACCIÓN 97
6-dic-2021 NOMBREACCIÓN 101
7-dic-2021 NOMBREACCIÓN 99
8-dic-2021 NOMBREACCIÓN 98
9-dic-2021 NOMBREACCIÓN 97
10-dic-2021 NOMBREACCIÓN 96
13-dic-2021 NOMBREACCIÓN 102
14-dic-2021 NOMBREACCIÓN 99
15-dic-2021 NOMBREACCIÓN 98
16-dic-2021 NOMBREACCIÓN 97
17-dic-2021 NOMBREACCIÓN 96
20-dic-2021 NOMBREACCIÓN 95
21-dic-2021 NOMBREACCIÓN 99
22-dic-2021 NOMBREACCIÓN 102
23-dic-2021 NOMBREACCIÓN 103
24-dic-2021 NOMBREACCIÓN 114

Resultado esperado:

ninguno
seguridad   numero_de_dias
NOMBREACCIÓN 6
Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para cumplir con el requisito anterior en MySQL 8.X, podemos utilizar el método de lagunas e islas junto con las funciones de ventana para identificar los períodos continuos en los que el market_price es menor que el valor objetivo (en este caso, 100). Luego, podemos contar el número de días en cada uno de estos períodos y filtrar aquellos que tienen al menos 6 días hábiles consecutivos. Aquí está la consulta SQL para hacer esto:

    CON RECURSIVE fechas AS (
      SELECT MIN(fecha_efectiva) AS fecha_minima, MAX(fecha_efectiva) AS fecha_maxima
      FROM nombre_tabla
      WHERE DAYOFWEEK(fecha_efectiva) BETWEEN 2 AND 6 -- considera solo días de la semana
    ),
    precios AS (
      SELECT d.fecha_minima, d.fecha_maxima, t.seguridad, t.fecha_efectiva, t.market_price,
        ROW_NUMBER() OVER (PARTITION BY t.seguridad, t.market_price < 100 ORDER BY t.fecha_efectiva) AS rn
      FROM fechas d
      CROSS JOIN (SELECT DISTINCT seguridad FROM nombre_tabla) s
      LEFT JOIN nombre_tabla t ON t.fecha_efectiva BETWEEN d.fecha_minima AND d.fecha_maxima AND t.seguridad = s.seguridad
      WHERE DAYOFWEEK(t.fecha_efectiva) BETWEEN 2 AND 6 -- considera solo días de la semana
    ),
    grupos AS (
      SELECT seguridad, market_price, MIN(fecha_efectiva) AS fecha_inicio, MAX(fecha_efectiva) AS fecha_fin, COUNT(*) AS dias
      FROM precios
      WHERE market_price < 100
      GROUP BY seguridad, market_price, DATE_SUB(fecha_efectiva, INTERVAL rn DAY)
    ),
    islas AS (
      SELECT seguridad, market_price, fecha_inicio, fecha_fin, dias,
        ROW_NUMBER() OVER (PARTITION BY seguridad, market_price ORDER BY fecha_inicio) -
          ROW_NUMBER() OVER (PARTITION BY seguridad, market_price, market_price < 100 ORDER BY fecha_inicio) AS grp
      FROM grupos
    ),
    filtrados AS (
      SELECT seguridad, SUM(dias) AS numero_de_dias
      FROM islas
      WHERE market_price < 100
      GROUP BY seguridad, grp
      HAVING COUNT(*) >= 6
    )
    SELECT seguridad, SUM(numero_de_dias) AS numero_de_dias
    FROM filtrados
    GROUP BY seguridad
    

    Vamos a través de cada CTE y el resultado final paso a paso:

    1. fechas: Este CTE encuentra las fechas efectivas mínima y máxima en la tabla y considera solo los días de la semana (de lunes a viernes).
    2. precios: Este CTE genera una lista de fechas para cada seguridad entre la fecha mínima y máxima (del CTE fechas), y realiza uniones izquierdas con la tabla en esas fechas para obtener el market_price. Utilizamos una función de ventana para generar números de fila para cada período continuo donde el market_price es menor que 100.

    3. grupos: Este CTE agrupa los períodos contiguos donde el market_price es menor que 100 por seguridad y market_price, y calcula el número de días en cada período.

    4. islas: Este CTE utiliza el método de lagunas e islas para asignar un número de grupo a cada período contiguo donde el market_price es menor que 100. Utilizamos otra función de ventana para calcular la diferencia entre los números de fila y agrupar por la seguridad, market_price y esta diferencia para asignar un número de grupo a cada período contiguo.

    5. filtrados: Este CTE filtra los períodos contiguos que tienen al menos 6 días hábiles donde el market_price es menor que 100.

    6. La instrucción SELECT final suma el número_de_dias en los períodos filtrados para cada seguridad.

    Ten en cuenta que debes reemplazar nombre_tabla con el nombre real de tu tabla en la consulta.

Comments are closed.