none
Varios SELECTS con misma CONDICION y resultados no separados RRS feed

  • Pregunta

  • Buenas a todos y gracias de antemano por vuestra atención.
    Mi duda es la siguiente:

    Tengo una tabla con unos 700 datos aprox con ID autoincremental y con estos campos:

    +------+------+------+------+
    | id   | pos_1 | pos_2 | pos_3 |
    +------+------+------+------+
    |    1 |       9 |        2 |        3 |
    |    2 |       3 |        2 |        9 |
    |    3 |       1 |        4 |        3 |
    |    4 |       1 |        2 |        3 |
    |    5 |       5 |        1 |        6 |
    |    6 |       1 |        2 |        3 |
    |    7 |       8 |        2 |        0 |
    |  ...  |     ... |      .. . |       ... |
    |  etc |    etc |     etc |      etc |
    +------+------+------+------+

    Sucede que yo realizo siempre una consulta que contiene varios selects y una condición en común, todo unido por "UNION" de esta manera:

    select *
        from listado T1 
         where pos_1 = ***  and pos_2 = ***  and pos_3 = ***       and exists (
           select id
           from listado T2
           where
         T2.pos_1 = ***  and pos_2 = ***  and pos_3 = ***  
    
     
      and T2.id >= T1.id - 10
                and T2.id <= T1.id + 10
         and T1.id != T2.id )
         
         UNION
         
         select *
        from listado T3 
         where pos_1 = ***  and pos_2 = ***  and pos_3 = ***    and exists (
           select id
           from listado T4
           where
         T4.pos_1 = ***  and pos_2 = ***  and pos_3 = *** 
    
      and T4.id >= T3.id - 10
                and T4.id <= T3.id + 10
         and T3.id != T4.id )
         
         UNION
         
         select *
        from listado T5 
         where pos_1 = ***  and pos_2 = ***  and pos_3 = ***    and exists (
           select id
           from listado T6
           where
         T6.pos_1 = ***  and pos_2 = ***  and pos_3 = *** 
      and T6.id >= T5.id - 10
                and T6.id <= T5.id + 10
         and T5.id != T6.id )
         
         
         ORDER BY id ASC

    De tal manera que esta consulta me devuelve las filas que coincidan con los números que yo he introducido en las posiciones correspondientes (pos_1,pos_2,pos_3) de la tabla, PERO con la condición de que los RESULTADOS de esta búsqueda no DISTEN entre sí mas de 10 POSICIONES por ID como podéis ver que hago con el fragmento:  

     and T***.id >= T***.id - 10
                and T***.id <= T***.id + 10
         and T***.id != T***.id )

    Hasta aquí todo correcto, el problema está en que al realizar esta consulta tal como está hecha los RESULTADOS que me devuelve son los SELECTS de forma independiente unos de otros... osea que está omitiendo TODOS los resultados que entremezclen las filas de los 3 SELECTS si es que así deba ser porque así aparezca en la tabla. Me esta sacando los resultados POR SEPARADO y no tengo ni idea de cómo acomodar la consulta para poder hacerlo... Compartiendo la condición de que los resultados no disten entre si por ID mas de 10 posiciones y conjuntamente POR EJEMPLO la linea de resultado del SELECT nº1 este dentro de la linea del resultado del SELECT Nº2 o del Nº3 si es que debe estarlo porque así se encuentre en la TABLA...

    El ejemplo gráfico de este problema sería colocando por ejemplo en los SELECTS estas consultas:

    1º SELECT: 0 - 1 - 4

    2º SELECT: 2 - 4 - 8

    3º SELECT: 3 - 5 - 6

    Aplicada la consulta tal cuál como está ahora devolvería:

    82  0   1   4
    83  0   1   4
    86  0   1   4
    16  2   4   8
    20  2   4   8
    24  2   4   8
    256 3   5   6
    260 3   5   6
    262 3   5   6

    Como se aprecia muestra los resultados de las lineas que coinciden en la tabla por separado pero esta omitiendo estos otros resultados que TAMBIÉN se encuentran en la base de datos de la tabla:

    82  0   1   4
    84  3   5   6
    86  0   1   4
    89  3   5   6
    --- --- --- ---
    90  3   5   6
    91  2   4   8

    Este resultado ultimo es el que debería aparecer pero no sé como acomodar el código para poder hacerlo...

    Gracias[;-)]



    • Editado marcosmrc domingo, 7 de abril de 2019 15:20
    domingo, 7 de abril de 2019 15:17

Respuestas

  • Hola marcosmrc:

    Si he entendido bien tu explicación.

    DECLARE @TABLEPOSICIONES TABLE (POS1 INT, POS2 INT, POS3 INT)
    INSERT INTO @TABLEPOSICIONES (POS1, POS2, POS3)
    VALUES
    (0,1,4),
    (2,4,8),
    (3,5,6);
    
    SELECT T1.* FROM LISTADO T1 INNER JOIN @TABLEPOSICIONES P ON T1.POS1 = P.POS1 AND T1.POS2 = P.POS2 AND T1.POS3 = P.POS3
    WHERE
     EXISTS(
    SELECT * FROM LISTADO T2 INNER JOIN @TABLEPOSICIONES P2 ON T2.POS1 = P2.POS1 AND T2.POS2 = P2.POS2 AND T2.POS3 =P2.POS3
    WHERE 
        T2.ID >= T1.ID - 10
    AND T2.ID <= T1.ID + 10
    AND T1.ID <> T2.ID )
    Solo tienes que meter los resultados a buscar en una variable tipo tabla, y cruzarla con tu origen de datos, como es una inner join, ya te lo da resuelto.

    • Propuesto como respuesta Carlos_Ruiz_M lunes, 8 de abril de 2019 14:35
    • Marcado como respuesta marcosmrc lunes, 15 de abril de 2019 14:43
    domingo, 7 de abril de 2019 18:15
  • Hola marcosmrc:

    En vez de utilizar declare, puedes usar una tabla normal.

    Create table......

    Cada vez que vayas a usar la sentencia borras, las filas anteriores, e insertas las nuevas.

    No creo que te compense, pero si quieres puedes instalarte un sql server express o developer edition. Son ediciones gratuitas. La primera con limitaciones de "potencia", la segunda sin ellas, pero no se puede poner en producción.

    Sql server

    https://www.microsoft.com/es-es/sql-server/sql-server-downloads

    Instalacion

    https://www.campusmvp.es/recursos/post/como-instalar-sql-server.aspx

    Yo para simular tu tabla, me hice un código para crear la tabla con números aleatorios.Y a partir de este reproduje tu escenario.

    CREATE TABLE LISTADO (ID INT IDENTITY(1,1), POS1 INT, POS2 INT, POS3 INT);
    GO
    ;WITH R AS (
    		 SELECT 1 AS C UNION ALL SELECT 1),
        R1 AS (SELECT 1 AS C FROM R  AS A CROSS JOIN R  AS B),
        R2 AS (SELECT 1 AS C FROM R1 AS A CROSS JOIN R1 AS B),
        R3 AS (SELECT 1 AS C FROM R2 AS A CROSS JOIN R2 AS B),
        R4 AS (SELECT 1 AS C FROM R3 AS A CROSS JOIN R3 AS B),
        R5 AS (
    	   SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS FILA FROM R4),
        Filas As(
    	   SELECT  TOP (700) R5.FILA FROM R5
    )
    INSERT INTO LISTADO 
    SELECT 
        1.0 + floor(9 * RAND(convert(varbinary, newid()))) POS1,
        1.0 + floor(9 * RAND(convert(varbinary, newid()))) POS2,
        1.0 + floor(9 * RAND(convert(varbinary, newid()))) POS3
    FROM Filas;
    Espero te ayude

    • Propuesto como respuesta Carlos_Ruiz_M lunes, 8 de abril de 2019 14:35
    • Marcado como respuesta marcosmrc lunes, 15 de abril de 2019 14:43
    lunes, 8 de abril de 2019 4:12
  • Hola marcosmrc:

    Del entorno web de phpmyAdmin, la verdad es que lo he tocado muy poco y no con mucho agrado. En mySql, bastante más.

    Pero si lo que haces lo integras en una tabla (puedes crearla con el entorno web), y realizas las insercciones con insert o de modo visual, y luego corres la consulta, no debiera de darte ningún error.

    A lo mejor el t1.id<> t2.id que sea como tu pusiste !=..... eso es algo que desconozco.

    Seguro que esto te sobra, pero por si acaso.

    https://www.liquidweb.com/kb/creating-tables-in-a-database-with-phpmyadmin/

    • Marcado como respuesta marcosmrc lunes, 15 de abril de 2019 14:43
    lunes, 8 de abril de 2019 11:59
  • Un saludo Javi,

    Lo primero de todo impresionante tu ayuda en mi problema, la verdad es que es de agradecer gente con tu capacidad para ayudar a los demás en los foros con sus problemas de esta manera tan precisa.

    Y analizando lo que me indicas, yo he probado el código que me propusiste en la respuesta anterior y me daba problemas al ejecutar la consulta en la consola de Mysql. Entendiendo lógicamente que es código Transact-sql para Sql-server y por eso no me funciona... Cómo es bastante necesario e importante para mí trabajo poder resolver este problema no me importa recurrir a Sql-server e instalarlo para poder resolver este problema y lo que se precise necesario, ningún inconveniente. Entiendo que la simulación que te has molestado en realizar (y agradezco) ha sido siempre en ese entorno con Transact-SQL, no obstante me indicas que puedo acomodar mi código a Mysql con CREATE TABLE en vez de DECLARE no? el código quedaría así entiendo:

    CREATE TABLE POSICIONES TABLE (POS1 INT, POS2 INT, POS3 INT)
    INSERT INTO POSICIONES (POS1, POS2, POS3)
    VALUES
    (0,1,4),
    (2,4,8),
    (3,5,6);
    
    SELECT T1.* FROM LISTADO T1 INNER JOIN TABLE POSICIONES P ON T1.POS1 = P.POS1 AND T1.POS2 = P.POS2 AND T1.POS3 = P.POS3
    WHERE
     EXISTS(
    SELECT * FROM LISTADO T2 INNER JOIN TABLE POSICIONES P2 ON T2.POS1 = P2.POS1 AND T2.POS2 = P2.POS2 AND T2.POS3 =P2.POS3
    WHERE 
        T2.ID >= T1.ID - 10
    AND T2.ID <= T1.ID + 10
    AND T1.ID <> T2.ID )
    

    Este código me sigue dando varios errores en la consola de Mysql de Phpmyadmin y realmente no sé como acomodarlo correctamente... perdona mi falta de experiencia Javi, seguro que es una tontería que no logro ver...

    Gracias de nuevo :)

    • Marcado como respuesta marcosmrc lunes, 15 de abril de 2019 14:43
    lunes, 8 de abril de 2019 10:34

Todas las respuestas

  • Hola marcosmrc:

    Si he entendido bien tu explicación.

    DECLARE @TABLEPOSICIONES TABLE (POS1 INT, POS2 INT, POS3 INT)
    INSERT INTO @TABLEPOSICIONES (POS1, POS2, POS3)
    VALUES
    (0,1,4),
    (2,4,8),
    (3,5,6);
    
    SELECT T1.* FROM LISTADO T1 INNER JOIN @TABLEPOSICIONES P ON T1.POS1 = P.POS1 AND T1.POS2 = P.POS2 AND T1.POS3 = P.POS3
    WHERE
     EXISTS(
    SELECT * FROM LISTADO T2 INNER JOIN @TABLEPOSICIONES P2 ON T2.POS1 = P2.POS1 AND T2.POS2 = P2.POS2 AND T2.POS3 =P2.POS3
    WHERE 
        T2.ID >= T1.ID - 10
    AND T2.ID <= T1.ID + 10
    AND T1.ID <> T2.ID )
    Solo tienes que meter los resultados a buscar en una variable tipo tabla, y cruzarla con tu origen de datos, como es una inner join, ya te lo da resuelto.

    • Propuesto como respuesta Carlos_Ruiz_M lunes, 8 de abril de 2019 14:35
    • Marcado como respuesta marcosmrc lunes, 15 de abril de 2019 14:43
    domingo, 7 de abril de 2019 18:15
  • Hola Javi, gracias por la respuesta.

    Yo uso phpmyadmin y parece no ser compatible con "DECLARE" o con "@", nobstante para poder probar el código que me propones instalaré el SQLserver o el programa que sea necesario y que me sirva. Nose si existe algún programa tipo studio o visualizador para hacer pruebas al que le pueda exportar la base de datos que contiene la tabla en cuestión de mi problema o directamente lo mejor es un SQL Server?

    Gracias



    • Editado marcosmrc domingo, 7 de abril de 2019 21:35
    domingo, 7 de abril de 2019 21:29
  • Hola marcosmrc:

    En vez de utilizar declare, puedes usar una tabla normal.

    Create table......

    Cada vez que vayas a usar la sentencia borras, las filas anteriores, e insertas las nuevas.

    No creo que te compense, pero si quieres puedes instalarte un sql server express o developer edition. Son ediciones gratuitas. La primera con limitaciones de "potencia", la segunda sin ellas, pero no se puede poner en producción.

    Sql server

    https://www.microsoft.com/es-es/sql-server/sql-server-downloads

    Instalacion

    https://www.campusmvp.es/recursos/post/como-instalar-sql-server.aspx

    Yo para simular tu tabla, me hice un código para crear la tabla con números aleatorios.Y a partir de este reproduje tu escenario.

    CREATE TABLE LISTADO (ID INT IDENTITY(1,1), POS1 INT, POS2 INT, POS3 INT);
    GO
    ;WITH R AS (
    		 SELECT 1 AS C UNION ALL SELECT 1),
        R1 AS (SELECT 1 AS C FROM R  AS A CROSS JOIN R  AS B),
        R2 AS (SELECT 1 AS C FROM R1 AS A CROSS JOIN R1 AS B),
        R3 AS (SELECT 1 AS C FROM R2 AS A CROSS JOIN R2 AS B),
        R4 AS (SELECT 1 AS C FROM R3 AS A CROSS JOIN R3 AS B),
        R5 AS (
    	   SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS FILA FROM R4),
        Filas As(
    	   SELECT  TOP (700) R5.FILA FROM R5
    )
    INSERT INTO LISTADO 
    SELECT 
        1.0 + floor(9 * RAND(convert(varbinary, newid()))) POS1,
        1.0 + floor(9 * RAND(convert(varbinary, newid()))) POS2,
        1.0 + floor(9 * RAND(convert(varbinary, newid()))) POS3
    FROM Filas;
    Espero te ayude

    • Propuesto como respuesta Carlos_Ruiz_M lunes, 8 de abril de 2019 14:35
    • Marcado como respuesta marcosmrc lunes, 15 de abril de 2019 14:43
    lunes, 8 de abril de 2019 4:12
  • Un saludo Javi,

    Lo primero de todo impresionante tu ayuda en mi problema, la verdad es que es de agradecer gente con tu capacidad para ayudar a los demás en los foros con sus problemas de esta manera tan precisa.

    Y analizando lo que me indicas, yo he probado el código que me propusiste en la respuesta anterior y me daba problemas al ejecutar la consulta en la consola de Mysql. Entendiendo lógicamente que es código Transact-sql para Sql-server y por eso no me funciona... Cómo es bastante necesario e importante para mí trabajo poder resolver este problema no me importa recurrir a Sql-server e instalarlo para poder resolver este problema y lo que se precise necesario, ningún inconveniente. Entiendo que la simulación que te has molestado en realizar (y agradezco) ha sido siempre en ese entorno con Transact-SQL, no obstante me indicas que puedo acomodar mi código a Mysql con CREATE TABLE en vez de DECLARE no? el código quedaría así entiendo:

    CREATE TABLE POSICIONES TABLE (POS1 INT, POS2 INT, POS3 INT)
    INSERT INTO POSICIONES (POS1, POS2, POS3)
    VALUES
    (0,1,4),
    (2,4,8),
    (3,5,6);
    
    SELECT T1.* FROM LISTADO T1 INNER JOIN TABLE POSICIONES P ON T1.POS1 = P.POS1 AND T1.POS2 = P.POS2 AND T1.POS3 = P.POS3
    WHERE
     EXISTS(
    SELECT * FROM LISTADO T2 INNER JOIN TABLE POSICIONES P2 ON T2.POS1 = P2.POS1 AND T2.POS2 = P2.POS2 AND T2.POS3 =P2.POS3
    WHERE 
        T2.ID >= T1.ID - 10
    AND T2.ID <= T1.ID + 10
    AND T1.ID <> T2.ID )
    

    Este código me sigue dando varios errores en la consola de Mysql de Phpmyadmin y realmente no sé como acomodarlo correctamente... perdona mi falta de experiencia Javi, seguro que es una tontería que no logro ver...

    Gracias de nuevo :)

    • Marcado como respuesta marcosmrc lunes, 15 de abril de 2019 14:43
    lunes, 8 de abril de 2019 10:34
  • Hola marcosmrc:

    Del entorno web de phpmyAdmin, la verdad es que lo he tocado muy poco y no con mucho agrado. En mySql, bastante más.

    Pero si lo que haces lo integras en una tabla (puedes crearla con el entorno web), y realizas las insercciones con insert o de modo visual, y luego corres la consulta, no debiera de darte ningún error.

    A lo mejor el t1.id<> t2.id que sea como tu pusiste !=..... eso es algo que desconozco.

    Seguro que esto te sobra, pero por si acaso.

    https://www.liquidweb.com/kb/creating-tables-in-a-database-with-phpmyadmin/

    • Marcado como respuesta marcosmrc lunes, 15 de abril de 2019 14:43
    lunes, 8 de abril de 2019 11:59
  • Me pongo a ello ahora mismo!, mil gracias de nuevo Javi cómo siempre aprendiendo de los que saben y mejorando cada día más! ;)


    • Editado marcosmrc lunes, 8 de abril de 2019 12:11
    lunes, 8 de abril de 2019 12:10