New question

Question:

Date: 03-09-2015 11:04:24 (In Spanish)

Consulta MySQL - Relacionar tablas por campos desnormalizados[Resolved]

Buanas tardes a todos:

Introito:

Imaginemos tengo 2 tablas
tabla_a (id_a, n_telefono, nombre)
tabla_b (id_b, n_telefono, msn, fecha)

Ahora bien:

Supongamos que quiero hacer una consulta, donde coincidan en ambas tablas los n_telefono

Las consultas Mysql podrian ser asi:

SELECT *
FROM tabla_a, tabla_b
WHERE tabla_a.n_telefono = tabla_b.n_telefono
ORDER BY fecha DESC

o tambien asi:

SELECT *
FROM tabla_a
INNER JOIN tabla_b
ON tabla_a.n_telefono = tabla_b.n_telefono;

Hasta aqui sencillo, ningun problema.

Ahora vamos a lo mas complicado:

Tengo la tabla_b (id_b, n_telefono, msn, fecha)
Con un campo n_telefonos.

Mediante un Form se ingresan los registros, donde el input del campo n_telefono, es un selector multiple, enviandome registros que pueden tener las siguientes caracteristicas:

Ejemplo:

Campo: n_telefono
INPUT - Select multiple:
Caso a) Registro = 40408080 (CARACTERES)
Caso b) Registro = 40408080, 30305050, 60609090, 10102050 (CADENA DE CARACTERES)

En el Caso a) recibio un solo numeros de telefono,
En el Caso b) recibio varios numeros de telefono, separados por una "," (COMA) como separador

Si yo hago las consultas que expuse, solo obtengo los registros, donde coinciden los n_telefono siempre y cuando en el campo de la tabla_b campo n_numero el registro sea de caracteres, si es tadena de caracteres no los lee.

En mi caso debo obtener todos los msn que se enviaron mediante una tabla a todos los n_telefono

Pregunta

¿Como deberia hacer la consulta para obtener el resultado pretendido?

A mi se me ocurre un foreach, pero no logro encontar la solucion

Desde ya muchas gracias a los que puedan colaborar


Tags: MySQL - MySQL Developing - Query - Question - SQL - SQL Stored Procedure Votes: 0 - Answers: 16 - Views: 17 Share on: Google Facebook Twitter LinkedIn Link
 

Answers:

  • Date: 04-09-2015 05:37:25 Hola Daniel, según entiendo estas necesitando filtrar el resultado del INNER JOIN con la lista de telefonos que te llegan por parametro, no?

    Si es así, simplemente puede usar algo como un WHERE con la instrucción IN.

    Por ejemplo:
    SELECT *
    FROM tabla_a
    INNER JOIN tabla_b
    ON tabla_a.n_telefono = tabla_b.n_telefono
    WHERE tabla_b.n_telefono IN (40408080, 30305050, 60609090, 10102050);


    Espero haber comprendido bien tu problema, cualquier cosa me dices.

    Saludos,
    Fernando
      Votes: 0 - Link answer
     
  • Date: 04-09-2015 06:08:58 Fernando:

    Ante todo, gracias por tu respuesta.

    SELECT *
    FROM tabla_a
    INNER JOIN tabla_b
    ON tabla_a.n_telefono = tabla_b.n_telefono
    WHERE tabla_b.n_telefono IN (40408080, 30305050, 60609090, 10102050);

    En el ejemplo que me das, es para el caso en que yo quiera consultar esos números determinados.
    Dando un resultado similar al que tengo.

    Cuando el usuario envían un msn los hacen por medio de un SELECTOR MULTIPLE, por lo tanto puede enviar un mensaje a uno o varios números de teléfono, alojándose ese dato en la tabla: tabla_b - Campo: n_telefono, a veces puede contener una cadena de caracteres, delimitado por comas (,).
    El campo puede recibir un registro (con un numero de teléfono) o también, puede recibir un registro (que contenga varios números de teléfono), como esta delimitado, puede tomar un formato de array().

    Se que tengo que comparar:

    tabla_a.n_telefono = tabla_b.n_telefono

    El tema es que:

    tabla_a.n_telefono tiene el teléfono de cada cliente
    tabla_b.n_telefono tiene los números de teléfono a los que han llamado, solo que puede haber un registro con un solo numero (Alli la consulta funciona bien) o puede tener como registro varios números de teléfono (40408080, 30305050, 60609090, 10102050, etc).

    ¿Espero que se comprenda mi pregunta?

    Nuevamente gracias
    Daniel
      Votes: 0 - Link answer
     
  • Date: 04-09-2015 07:33:09 Hola Daniel:

    Creo que lo que deberíamos hacer es recorrer el campo como array, en tu caso, el segundo elemento comparativo (tabla_b.n_telefono).

    Desde mi inexperiencia (nunca me enfrenté a un caso similar) la variedad en el tratamiento de arrays la tienes, como página de base, en http://php.net/manual/es/book.array.php

    El camino posiblemente no sea el mejor pero sería meter la consulta FROM tabla_a INNER JOIN tabla_b dentro del for correspondiente.
      Votes: 0 - Link answer
     
  • Date: 04-09-2015 08:24:20 Ahora creo entender un poco mejor, fijate con esta query, aquí aplique la función de MySQL FIND_IN_SET

    SELECT *
        FROM tabla_a
        INNER JOIN tabla_b
        ON (FIND_IN_SET(tabla_a.n_telefono,tabla_b.n_telefono)>0);


    Saludos!
      Votes: 0 - Link answer
     
  • Date: 04-09-2015 10:41:03 Fernando, Artzain
    Gracias nuevamente por su colaboracion:

    Fernando, con la consulta que me envias, obtengo todos los registros por cada msn que se envio.
    Lo que sigo sin obtener es:
    Por cada n_telefono que figure en la cadena de caracteres el nombre de cada uno

    Comento:
    Probe con un foreach
    [foreach(explode(',', $n_telefono) as $numero


    Donde psteriormente por medio de otra consulta $numero sea una variable y tampco resulto

    Daniel
      Votes: 0 - Link answer
     
  • Date: 04-09-2015 13:07:13 La query que te pase te puede devolver el nombre de todos los teléfonos relacionados sin repetidos usando un GROUP BY

    SELECT tabla_a.nombre
    FROM tabla_a 
    INNER JOIN tabla_b 
    ON (FIND_IN_SET(tabla_a.n_telefono,tabla_b.n_telefono)>0)
    GROUP BY tabla_a.id_a;
      Votes: 0 - Link answer
     
  • Date: 04-09-2015 14:21:23 Fernando:

    Nuevamente gracias por tu respuesta

    Aca veras graficamente lo que pretendo

    tabla_a 
    Campos
    id_a   |   n_telefono   |    nombre
       1         11111111         Pepe
       2         22222222         Tito
       3         33333333         Tato
    
    tabla_b
    Campos
    id_b   |       fecha        |  msn  | n_telefono   |   
       1         2015-01-01        Hola    11111111        
       2         2015-03-04        Paz     11111111, 2222222, 33333333        
       3         2015-04-01        SOS     3333333  
    
    ***Recuerdo que el Campo n_telefono, puede recibir: 
    a) Un conjunto de caracteres Ejemplo: 11111111
    b) Una cadena de caracteres Ejemplo: 11111111, 2222222, 33333333
    
    Resultado PRETENDIDO
    
         fecha     |  msn  | n_telefono   |   Nombre
     2015-01-01      Hola     11111111        Pepe
     2015-03-04      Paz      11111111        Pepe
     2015-03-04      Paz      22222222        Tito
     2015-03-04      Paz      33333333        Tato 
     2015-04-01      SOS      33333333        Tato
    
    Resultado NO DESEADO
    
       fecha  |  msn  | n_telefono                  | Nombre
    2015-01-01   Hola   11111111                       Pepe
    2015-03-04   Paz    11111111, 22222222, 3333333        
    2015-04-01   SOS    33333333                       Tato
    


    Daniel
      Votes: 0 - Link answer
     
  • Date: 05-09-2015 04:22:59 Creación de tablas y modelo de datos para intentar obtener el resultado correcto (100% ejecutable en MySQL Community Edition):

    Creo las tablas y las cargo con los datos dummy:
    CREATE TABLE `tabla_a` (
      `id_a` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `n_telefono` varchar(250) DEFAULT NULL,
      `nombre` varchar(250) DEFAULT NULL,
      PRIMARY KEY (`id_a`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
    
    INSERT INTO tabla_a VALUES
    (1,'11111111', 'Pepe'),
    (2,'22222222', 'Tito'),
    (3,'33333333', 'Tato');
    
    CREATE TABLE `tabla_b` (
      `id_b` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `fecha` date DEFAULT NULL,
      `msn` varchar(250) DEFAULT NULL,
      `n_telefono` varchar(250) DEFAULT NULL,
      PRIMARY KEY (`id_b`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
    
    INSERT INTO tabla_b VALUES
    (1, '2015-01-01', 'Hola', '11111111'),
    (2, '2015-03-04', 'Paz', '11111111, 22222222, 33333333'),
    (3, '2015-04-01', 'SOS', '33333333');


    ---------------
    Si quieres obtener el resultado no deseado, aquí las query's

    Ajustando los campos SELECT

    SELECT tabla_b.fecha, tabla_b.msn, tabla_b.n_telefono, tabla_a.nombre
    FROM tabla_a
    INNER JOIN tabla_b
    ON (FIND_IN_SET(tabla_a.n_telefono,tabla_b.n_telefono)>0);


    Si perfecciono el SELECT con un CASE para devolver nombre vacío cuando hay más de un telefono (aquí el resultado es mas exacto)
    SELECT tabla_b.fecha, tabla_b.msn, tabla_b.n_telefono,
    CASE
    	WHEN locate(',',tabla_b.n_telefono)>0  THEN ''
    	ELSE tabla_a.nombre
    END
    FROM tabla_a
    INNER JOIN tabla_b
    ON (FIND_IN_SET(tabla_a.n_telefono,tabla_b.n_telefono)>0);



    Resultado no deseado:
    2015-01-01	Hola	11111111	Pepe
    2015-03-04	Paz	11111111, 22222222, 33333333	
    2015-04-01	SOS	33333333	Tato
    


    ---------------

    Lo anterior lo deje porque tal vez aporta alguna idea nueva, si encuentro la solución correcta la posteo.

    Saludos,
      Votes: 0 - Link answer
     
  • Date: 05-09-2015 04:48:44 Fernando:

    Gracias nuevamente
    Pero como te dije en mi POST anterior el:

    RESULTADO DESEADO
    
         fecha     |  msn  | n_telefono   |   Nombre
     2015-01-01      Hola     11111111        Pepe
     2015-03-04      Paz      11111111        Pepe
     2015-03-04      Paz      22222222        Tito
     2015-03-04      Paz      33333333        Tato 
     2015-04-01      SOS      33333333        Tato


    Daniel
      Votes: 1 - Link answer
     
  • Date: 05-09-2015 05:56:34 Daniel, disculpa la confusión, edite mi respuesta anterior para que por lo menos aporte algo y no confunda, si encuentro la solución correcta la posteo.

    Saludos,
      Votes: 0 - Link answer
     
  • Date: 05-09-2015 10:00:37 Fernando:
    Estoy tratando de buscar por PHP la solucion, encare por este lado:

    <?php
    
    $db = mysqli_connect("localhost","root","","mi_bd");
    $rs = mysqli_query($db,"SELECT * FROM tabla_b");
    
    	while ($row = mysqli_fetch_assoc($rs))
    
    	{ 
    
    	$array = array(
    					$id_b=$row['id_b'],
    					$fecha=$row['fecha'],
    					$msn=$row['msn'],
    					$n_telefono=$row['n_telefono']
    				   );
    
    
    	$telefono = explode(",", $n_telefono); 
    	print_r($telefono);
    
    	 }
    ?>


    OBTENGO ESTE RESULTADO:

    Array ( [0] => 11111111 ) Array ( [0] => 11111111 [1] => 2222222 [2] => 33333333 ) Array ( [0] => 33333333 )

    Lo que implica que estoy separando a la cadena de caracteres, lo que me permitiria hacer una nueva consulta en donde utilizando las 2 tablas comparando

    WHERE tabla_a.n_telefono = $array // o algo parecido

    Hasta aqui llegue, aun no lo he resuelto.

    Un saludo

    Daniel
      Votes: 0 - Link answer
     
  • Date: 06-09-2015 03:33:06 Buenos días Daniel, finalmente llegue a la solución por medio de un stored procedure al que llamé "sp_mensajes", aquí el código 100% funcional.

    Creación del stored procedure:
    DELIMITER $$
    
    DROP PROCEDURE IF EXISTS sp_mensajes $$
    CREATE PROCEDURE sp_mensajes()
      BEGIN
    	DECLARE separador VARCHAR(255) DEFAULT ',';
        DECLARE var_id_b INT DEFAULT 0;
        DECLARE var_fecha TEXT;
        DECLARE var_msn TEXT;
        DECLARE var_n_telefono TEXT;
        DECLARE ocurrencias INT DEFAULT 0;
        DECLARE i INT DEFAULT 0;
        DECLARE n_telefono_dividido INT;
        DECLARE done INT DEFAULT 0;
        DECLARE cursor_tabla_b CURSOR FOR
    		SELECT
    		    id_b,
    			fecha,
    		    msn,
    		    n_telefono
    		FROM tabla_b
    		WHERE tabla_b.n_telefono != '';
    
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
    
        DROP TEMPORARY TABLE IF EXISTS explode_tabla_b;
        CREATE TEMPORARY TABLE explode_tabla_b(
            `id_b` INT NOT NULL,
            `fecha` date DEFAULT NULL,
            `msn` varchar(250) DEFAULT NULL,
            `n_telefono` varchar(250) NOT NULL
        ) ENGINE=Memory DEFAULT CHARSET=utf8;
    
    
        OPEN cursor_tabla_b;
          read_loop: LOOP
            FETCH cursor_tabla_b INTO var_id_b,var_fecha,var_msn,var_n_telefono;
            IF done THEN
              LEAVE read_loop;
            END IF;
    
            SET ocurrencias = (SELECT LENGTH(var_n_telefono) - LENGTH(REPLACE(var_n_telefono, separador, '')) + 1);
    
            SET i=1;
            WHILE i <= ocurrencias DO
              SET n_telefono_dividido =
              (SELECT REPLACE(SUBSTRING(SUBSTRING_INDEX(var_n_telefono, separador, i),
              LENGTH(SUBSTRING_INDEX(var_n_telefono, separador, i - 1)) + 1), ',', ''));
    
              INSERT INTO explode_tabla_b VALUES (var_id_b,var_fecha,var_msn,n_telefono_dividido);
              SET i = i + 1;
    
            END WHILE;
          END LOOP;
    
          SELECT explode_tabla_b.fecha, explode_tabla_b.msn, explode_tabla_b.n_telefono, tabla_a.nombre
          FROM explode_tabla_b
          INNER JOIN tabla_a
          ON(tabla_a.n_telefono = explode_tabla_b.n_telefono);
    
          DROP TEMPORARY TABLE IF EXISTS explode_tabla_b;
        CLOSE cursor_tabla_b;
      END; $$
    
    DELIMITER ;
    


    Ejecución del stored procedure:
    CALL sp_mensajes();
    


    A modo de resumen, el stored procedure hacer un explode de la tabla_b y persiste el resultado en memoria (de forma temporal), finalmente hace el query (select, inner join, etc etc) y devuelve el resultado esperado.

    Espero que mi respuesta te sea de ayuda.

    Saludos,
    Fernando
      Votes: 3 - Link answer
     
  • Date: 07-09-2015 04:56:07 Fernando

    Muy agradecido por tu ayuda ...
    Pequeño inconveniente (Como no entiendo bien tu script ("por falta de conocimientos") no se como aplicarlo dentro del php)

    Gracias nuevamente

    Daniel
      Votes: 0 - Link answer
     
  • Date: 07-09-2015 05:29:44 Hola Daniel, lo que tienes que hacer es:

    1) Adaptar el stored procedure a tu base de datos (nombre de las tablas, cantidad y nombre de las columnas, nombre del stored procedure)
    2) Crear el strore procedure en la base de datos (o sea, ejecutar el CREATE PROCEDURE...)
    3) Ejecutar el stored procedure desde PHP, el mismo te devolverá la tabla "resultado deseado"
    4) Finalmente usar los datos devueltos por el stored procedure... :)

    Para ejecutar el stored procedure desde PHP (con MySQLi) puedes hacer algo como:
    <?php 
    //conectar a la base de datos
    $connection = mysqli_connect("hostname", "user", "password", "db", "port");
    
    //ejecutar el stored procedure
    $result = mysqli_query($connection, "CALL sp_mensajes") or die("Query fail: " . mysqli_error());
    
    //iterar el result set
    while ($row = mysqli_fetch_array($result)){   
        echo $row['fecha'] . ' - ' . $row['msn']. ' - ' . $row['n_telefono']. ' - ' . $row['nombre'] . '<br/>'; 
    }
    ?>


    Saludos,
    Fernando
      Votes: 1 - Link answer
     
  • Date: 09-09-2015 12:32:05 Fernando:

    He aprendido en este breve tiempo que si uno pretende programar, no se puede rendir ante nada ...
    De hecho me resiste a que no existiera una posibilidad PHP para este tema.
    Tanto darme la cabeza contra las paredes, lo logre.
    La solucion estaba como siempre detras de un par de lineas de codigo, la cual expongo mas abajo, para quien la pueda necesitar:
    Desde ya agradezco infinitamente vuestra colaboracion y de ser nesesario contar con ustedes en a proxima.

    <?php
    /**
     * Creo Conexion
     */
    $db = mysqli_connect("localhost","root","","afip");
    /**
     * Habo una consulta a la tabla_b
     */
    $rs = mysqli_query($db,"SELECT * FROM tabla_b");
    
    	while ($row=mysqli_fetch_array($rs)) {												
    	//Obtengo los numeros de telefono independientemente si estan registrados de auno o en un array
    	$n_telefono = $row['n_telefono'];
    	/**
    	 * Creo una variable
    	 * @var [vector]
    	 */
    	$vector = $n_telefono;
        /**
         * Creo una nueva variable en donde contenga todos los numeros de telefono uno por uno
         * @var [separar]
         */
    	$separar = explode(",", $vector); 
        /**
         * Hago un foreach donde a cada numero de telefono que encuentre, le asigne un valor
         */
    	foreach($separar as $valor) {
    			
    /**
     * Creo una nueva consulta, pero esta vez entre las 2 tablas (Tabla_a y tabla_b), donde $valor tiene el registro de cada telefono
     * @var [valor] 
     */
    $xx = mysqli_query($db,"SELECT tabla_a.n_telefono, tabla_a.id_a, tabla_b.* 
    						FROM tabla_a, tabla_b
    						WHERE tabla_a.n_telefono = $valor");
    
    	{ 
    
    	$id_b=$row['id_b'];
    	$fecha=$row['fecha'];
    	$msn=$row['msn'];
    	$n_telefono=$row['n_telefono'];
    
    	echo $id_b ." ". $fecha ." ". $msn  ." ". $valor  ."<br />";
    
    }
    }
    }
    ?>

    Un saludo
    Daniel
    PD.: Doy la pregunta por RESUELTA
      Votes: 0 - Link answer
     
  • Date: 26-12-2018 06:51:40 vaya que buen POST justo estaba buscando algo similar el nivel de la consulta del Sr. fernando es buenísimo. mi pregunta para el Sr. fernando es si ese tipo de consultas es necesaria por seguridad o también se puede trabajar como lo hizo antuan? saludos   Votes: 0 - Link answer
     
To actively participate in the community first must authenticate, enter the system.Sign In
 
frjcbbae garagebible.com