none
Evitar Datos Duplicados en Consulta SQL de Multiples Tablas RRS feed

  • Pregunta

  • Saludos compañeros

    La verdad soy nuevo en esto de base de datos, y despues de tratar de solucionar mi problema y resultar en un total fracaso he decidido acudir a este foro.

    Actualmente estoy trabajando en una base de datos la cual contiene una tabla "Principal" si podemos decirlo asi, en la que varias tablas hacen referencia de esta.

    Tengo una tabla "Proyecto" (esta tabla sería la principal) y las que tienen una relacion con esta son: "colaboradores","actividades_vs_proyecto","desembolsos" y "gastos". Todas estas relacionadas con la llave foránea "idpro" (llava principal de la tabla "proyecto").

    A la hora de hacer una consulta entre todas estas tablas, obtengo como resultado datos duplicados. He recurrido al uso de las funciones "distinct" y "group by". Cuando uso la función "distinct" no se duplican los datos a la hora de la consulta, pero solo con algunos campos, me explico, solo me funciona cuando no agrego ningún campo de las tablas: "actividades","colaboradores", de lo contrario me sigue lanzando los datos duplicados.

    El codigo que utilizo para la consulta es :

    //Inicio del Codigo

    select distinct (de.desc_desem),d.desembolso,d.balance,po.nompro,po.fec_inicio,po.fec_final,g.nomact_gasto,g.gastado,
    (select (p.nomper + ' ' + p.apeper) as nombres),p.nomrol,a.nomact,a.estado

    from desembolsos d

            inner join proyecto po on d.idpro= po.idpro
            inner join desc_desembolso de on de.iddesem=d.iddesem
            inner join gastos g on g.idpro = po.idpro

            inner join colaboradores c on c.idpro = po.idpro
            inner join V_Consulta_Personal p on c.idper = p.idper
            inner join V_Actividades a on a.idpro = po.idpro
            
            where po.idpro = 1

    //Fin del Codigo

    viernes, 6 de septiembre de 2019 21:05

Respuestas

  • Hola Dna_Cypher:

    Tienes un pequeño error en el concepto de duplicado.

    Te propongo una lectura, que te ayudará a entenderlo (al menos eso espero)

    Group by

    https://javifer2.blogspot.com/search/label/group%20by

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

    Viendo tú consulta, es un poco difícil ayudarte, sin saber como se relacionan sus tablas. Por ejemplo, supongo que desembolsos tendrá muchas filas, por cada proyecto. Si esto es correcto, y tú quieres ver 1 solo desembolso por proyecto, habrá que utilizar las funciones de agregación Sum o Max. Pero si los quieres ver todos (supongo esto porque muestras la desc_desem), entonces no se utilizarán funciones de agregado.

    Lo mismo con cualquier tabla, hace falta saber cual es su tipo de relación, y también cuál es el resultado esperado.

    SELECT de.desc_desem, 
           d.desembolso, 
           d.balance, 
           po.nompro, 
           po.fec_inicio, 
           po.fec_final, 
           g.nomact_gasto, 
           g.gastado, 
           p.nomper + ' ' + p.apeper AS nombres, 
           p.nomrol, 
           a.nomact, 
           a.estado
    FROM desembolsos d
         INNER JOIN proyecto po ON d.idpro = po.idpro
         INNER JOIN desc_desembolso de ON de.iddesem = d.iddesem
         INNER JOIN gastos g ON g.idpro = po.idpro
         INNER JOIN colaboradores c ON c.idpro = po.idpro
         INNER JOIN V_Consulta_Personal p ON c.idper = p.idper
         INNER JOIN V_Actividades a ON a.idpro = po.idpro
    WHERE po.idpro = 1;

    No tiene sentido el uso de una subconsulta, en las columnas de la select, siempre que se pueda evitar. (y se puede).

    Select 
    …….
    p.nomper + ' ' + p.apeper, /*si tu SQL Server es mayor que 2012 puedes cambiarlo por */
    CONCAT(p.nomper, ' ', p.apeper) as nombres
    
    from ….
    El funcionamiento es idéntico a más, pero se ve mucho mejor, y es menos dado a errores.


    sábado, 7 de septiembre de 2019 6:31
  • Saludos amigo, gracias por responderme, aqui te dejo un diagrama de la base de datos para que puedas ver de manera mas detallada las relaciones.

    Respondiendo a tu inquietud, si, mi intencion es que salga cada desembolso que se haga (en total son 8

    Te dejare a continuacion las tablas que conforman la base de datos para que puedas ver las relaciones de mejor manera (estoy teniendo problemas con insertar la imagen del diagrama asi que esto es lo mejor que puedo hacer)

    //Tablas

    create table proyecto (

    idpro int primary key,

    nompro varchar,

    fec_inicio date,

    fec_final date)

    create table persona (

    idper int primary key,

    nomper varchar,

    apeper varchar,

    idsex int,

    idrol int)

    create table colaboradores (

    idper int,

    idpro int)

    create table roles (

    idrol int primary key,

    nomrol varchar)

    create table sexo (

    idsex int primary key,

    dessex varchar)

    create table desembolsos (

    iddesem int,

    desembolso float,

    idpro int,

    balance float)

    create table desc_desembolso (

    iddesem int primary key,

    desc_desem varchar)

    create table gastos (

    nomact_gasto varchar,

    gastado float,

    idpro int)

    create table actividades (

    idact int primary key,

    nomact varchar,

    estado varchar)

    create table actividades_vs_proyecto(

    idact int,

    idpro int)

    //Fin

    Gracias por responder!!!

    sábado, 7 de septiembre de 2019 23:34
  • Hola Dna_Cypher:

    Si bien la sentencia de creación de tablas no explicita que tipo de relaciones conlleva, salvo actividades_Vs_proyecto, entiendo que son todas con relación a proyecto 1 a n, dado que un proyecto, puede tener, n desembolsos, n gastos, y n colaboradores.

    Lo primero 1 pequeño matiz: Cambia esas definiciones de tabla con nombreColumna varchar por nombreColumna varchar(xx), donde xx es el número máximo de caracteres que quieres que te admita la columna, porque a posteriori te puede dar problemas.

    create table proyecto (
    idpro int primary key,
    /* sugerencia: establece el tamaño máximo por defecto de la columna */
    nompro varchar(30),
    fec_inicio date,
    fec_final date)
    
    create table persona (
    idper int primary key,
    nomper varchar(30),
    apeper varchar(30),
    idsex int,
    idrol int)
    
    create table colaboradores (
    idper int,
    idpro int)
    
    create table roles (
    idrol int primary key,
    nomrol varchar(30))
    
    create table sexo (
    idsex int primary key,
    dessex varchar(30))
    
    create table desembolsos (
    iddesem int,
    desembolso float,
    idpro int,
    balance float)
    
    create table desc_desembolso (
    iddesem int primary key,
    desc_desem varchar(30))
    
    create table gastos (
    nomact_gasto varchar(30),
    gastado float,
    idpro int)
    
    create table actividades (
    idact int primary key,
    nomact varchar(30),
    estado varchar(30))
    
    create table actividades_vs_proyecto(
    idact int,
    idpro int)
    go

    Con estos datos, yo he cargado los siguientes valores

    insert into  proyecto 
    (idpro,nompro,fec_inicio,fec_final)
    values
    (1,'pro1','20190101','20200101'),
    (2,'pro2','20190101','20200101');
    go
    insert into persona (idper, nomper, apeper, idsex, idrol)
    values
    (1,'Ana','Pérez',1,1),
    (2,'Luis','RioPedre',2,1),
    (3,'Carla','Urbano',2,1),
    (4,'Gervasio','Solís',1,1);
    go
    insert into colaboradores (idper, idpro)
    values
    (1,1),
    (2,1),
    (3,2),
    (4,2);
    go
    insert into roles (idrol, nomrol)
    values
    (1,'administrador')
    go
    insert into sexo
    (idsex, dessex)
    values
    (1,'Mujer'),
    (2,'Hombre');
    go
    insert into desembolsos 
    (iddesem, desembolso, idpro, balance)
    values
    (1 ,400 ,1,2000),
    (2 ,100 ,1,1900),
    (3 ,200 ,1,1800),
    (4 ,100 ,1,1700),
    (5 ,100 ,1,1600),
    (6 ,100 ,1,1500),
    (7 ,-100,1,1600),
    (8 ,100 ,1,1500),
    (9 ,100 ,2,1800),
    (10,400 ,2,1400),
    (11,100 ,2,1300),
    (12,200 ,2,1200);
    go
    insert into desc_desembolso
    (iddesem, desc_desem)
    values
    (1 ,'Apertura'),
    (2 ,'Mov2'),
    (3 ,'Mov3'),
    (4 ,'Mov4'),
    (5 ,'Mov5'),
    (6 ,'Mov6'),
    (7 ,'Mov7'),
    (8 ,'Mov8'),
    (9 ,'Apertura'),
    (10,'Mov2 2'),
    (11,'Mov3 2'),
    (12,'Mov4 2');
    GO
    INSERT INTO gastos
    (nomact_gasto, gastado, idpro)
    values
    ('pago1', 33, 1),
    ('pago2', 21, 1),
    ('pago3', 14, 1),
    ('pago4', 90, 2),
    ('pago5', 86, 2),
    ('pago6', 30, 2);
    go
    insert into actividades (idact, nomact, estado)
    values
    (1,'actividad1', 'activo'),
    (2,'actividad2', 'activo'),
    (3,'actividad3', 'activo'),
    (4,'actividad4', 'activo'),
    (5,'actividad5', 'activo'),
    (6,'actividad6', 'activo'),
    (7,'actividad7', 'activo'),
    (8,'actividad8', 'activo');
    go
    insert into actividades_vs_proyecto 
    (idact, idpro)
    values
    (1,1),
    (2,1),
    (3,1),
    (4,1),
    (5,2),
    (6,2),
    (7,2),
    (8,2);
    go
    
    

    Ahora para poder ayudarte necesito, que me pongas en una hoja de datos, cual es la salida esperada para esos valores.

     

    domingo, 8 de septiembre de 2019 2:40

Todas las respuestas

  • Hola Dna_Cypher:

    Tienes un pequeño error en el concepto de duplicado.

    Te propongo una lectura, que te ayudará a entenderlo (al menos eso espero)

    Group by

    https://javifer2.blogspot.com/search/label/group%20by

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

    Viendo tú consulta, es un poco difícil ayudarte, sin saber como se relacionan sus tablas. Por ejemplo, supongo que desembolsos tendrá muchas filas, por cada proyecto. Si esto es correcto, y tú quieres ver 1 solo desembolso por proyecto, habrá que utilizar las funciones de agregación Sum o Max. Pero si los quieres ver todos (supongo esto porque muestras la desc_desem), entonces no se utilizarán funciones de agregado.

    Lo mismo con cualquier tabla, hace falta saber cual es su tipo de relación, y también cuál es el resultado esperado.

    SELECT de.desc_desem, 
           d.desembolso, 
           d.balance, 
           po.nompro, 
           po.fec_inicio, 
           po.fec_final, 
           g.nomact_gasto, 
           g.gastado, 
           p.nomper + ' ' + p.apeper AS nombres, 
           p.nomrol, 
           a.nomact, 
           a.estado
    FROM desembolsos d
         INNER JOIN proyecto po ON d.idpro = po.idpro
         INNER JOIN desc_desembolso de ON de.iddesem = d.iddesem
         INNER JOIN gastos g ON g.idpro = po.idpro
         INNER JOIN colaboradores c ON c.idpro = po.idpro
         INNER JOIN V_Consulta_Personal p ON c.idper = p.idper
         INNER JOIN V_Actividades a ON a.idpro = po.idpro
    WHERE po.idpro = 1;

    No tiene sentido el uso de una subconsulta, en las columnas de la select, siempre que se pueda evitar. (y se puede).

    Select 
    …….
    p.nomper + ' ' + p.apeper, /*si tu SQL Server es mayor que 2012 puedes cambiarlo por */
    CONCAT(p.nomper, ' ', p.apeper) as nombres
    
    from ….
    El funcionamiento es idéntico a más, pero se ve mucho mejor, y es menos dado a errores.


    sábado, 7 de septiembre de 2019 6:31
  • Saludos amigo, gracias por responderme, aqui te dejo un diagrama de la base de datos para que puedas ver de manera mas detallada las relaciones.

    Respondiendo a tu inquietud, si, mi intencion es que salga cada desembolso que se haga (en total son 8

    Te dejare a continuacion las tablas que conforman la base de datos para que puedas ver las relaciones de mejor manera (estoy teniendo problemas con insertar la imagen del diagrama asi que esto es lo mejor que puedo hacer)

    //Tablas

    create table proyecto (

    idpro int primary key,

    nompro varchar,

    fec_inicio date,

    fec_final date)

    create table persona (

    idper int primary key,

    nomper varchar,

    apeper varchar,

    idsex int,

    idrol int)

    create table colaboradores (

    idper int,

    idpro int)

    create table roles (

    idrol int primary key,

    nomrol varchar)

    create table sexo (

    idsex int primary key,

    dessex varchar)

    create table desembolsos (

    iddesem int,

    desembolso float,

    idpro int,

    balance float)

    create table desc_desembolso (

    iddesem int primary key,

    desc_desem varchar)

    create table gastos (

    nomact_gasto varchar,

    gastado float,

    idpro int)

    create table actividades (

    idact int primary key,

    nomact varchar,

    estado varchar)

    create table actividades_vs_proyecto(

    idact int,

    idpro int)

    //Fin

    Gracias por responder!!!

    sábado, 7 de septiembre de 2019 23:34
  • Hola Dna_Cypher:

    Si bien la sentencia de creación de tablas no explicita que tipo de relaciones conlleva, salvo actividades_Vs_proyecto, entiendo que son todas con relación a proyecto 1 a n, dado que un proyecto, puede tener, n desembolsos, n gastos, y n colaboradores.

    Lo primero 1 pequeño matiz: Cambia esas definiciones de tabla con nombreColumna varchar por nombreColumna varchar(xx), donde xx es el número máximo de caracteres que quieres que te admita la columna, porque a posteriori te puede dar problemas.

    create table proyecto (
    idpro int primary key,
    /* sugerencia: establece el tamaño máximo por defecto de la columna */
    nompro varchar(30),
    fec_inicio date,
    fec_final date)
    
    create table persona (
    idper int primary key,
    nomper varchar(30),
    apeper varchar(30),
    idsex int,
    idrol int)
    
    create table colaboradores (
    idper int,
    idpro int)
    
    create table roles (
    idrol int primary key,
    nomrol varchar(30))
    
    create table sexo (
    idsex int primary key,
    dessex varchar(30))
    
    create table desembolsos (
    iddesem int,
    desembolso float,
    idpro int,
    balance float)
    
    create table desc_desembolso (
    iddesem int primary key,
    desc_desem varchar(30))
    
    create table gastos (
    nomact_gasto varchar(30),
    gastado float,
    idpro int)
    
    create table actividades (
    idact int primary key,
    nomact varchar(30),
    estado varchar(30))
    
    create table actividades_vs_proyecto(
    idact int,
    idpro int)
    go

    Con estos datos, yo he cargado los siguientes valores

    insert into  proyecto 
    (idpro,nompro,fec_inicio,fec_final)
    values
    (1,'pro1','20190101','20200101'),
    (2,'pro2','20190101','20200101');
    go
    insert into persona (idper, nomper, apeper, idsex, idrol)
    values
    (1,'Ana','Pérez',1,1),
    (2,'Luis','RioPedre',2,1),
    (3,'Carla','Urbano',2,1),
    (4,'Gervasio','Solís',1,1);
    go
    insert into colaboradores (idper, idpro)
    values
    (1,1),
    (2,1),
    (3,2),
    (4,2);
    go
    insert into roles (idrol, nomrol)
    values
    (1,'administrador')
    go
    insert into sexo
    (idsex, dessex)
    values
    (1,'Mujer'),
    (2,'Hombre');
    go
    insert into desembolsos 
    (iddesem, desembolso, idpro, balance)
    values
    (1 ,400 ,1,2000),
    (2 ,100 ,1,1900),
    (3 ,200 ,1,1800),
    (4 ,100 ,1,1700),
    (5 ,100 ,1,1600),
    (6 ,100 ,1,1500),
    (7 ,-100,1,1600),
    (8 ,100 ,1,1500),
    (9 ,100 ,2,1800),
    (10,400 ,2,1400),
    (11,100 ,2,1300),
    (12,200 ,2,1200);
    go
    insert into desc_desembolso
    (iddesem, desc_desem)
    values
    (1 ,'Apertura'),
    (2 ,'Mov2'),
    (3 ,'Mov3'),
    (4 ,'Mov4'),
    (5 ,'Mov5'),
    (6 ,'Mov6'),
    (7 ,'Mov7'),
    (8 ,'Mov8'),
    (9 ,'Apertura'),
    (10,'Mov2 2'),
    (11,'Mov3 2'),
    (12,'Mov4 2');
    GO
    INSERT INTO gastos
    (nomact_gasto, gastado, idpro)
    values
    ('pago1', 33, 1),
    ('pago2', 21, 1),
    ('pago3', 14, 1),
    ('pago4', 90, 2),
    ('pago5', 86, 2),
    ('pago6', 30, 2);
    go
    insert into actividades (idact, nomact, estado)
    values
    (1,'actividad1', 'activo'),
    (2,'actividad2', 'activo'),
    (3,'actividad3', 'activo'),
    (4,'actividad4', 'activo'),
    (5,'actividad5', 'activo'),
    (6,'actividad6', 'activo'),
    (7,'actividad7', 'activo'),
    (8,'actividad8', 'activo');
    go
    insert into actividades_vs_proyecto 
    (idact, idpro)
    values
    (1,1),
    (2,1),
    (3,1),
    (4,1),
    (5,2),
    (6,2),
    (7,2),
    (8,2);
    go
    
    

    Ahora para poder ayudarte necesito, que me pongas en una hoja de datos, cual es la salida esperada para esos valores.

     

    domingo, 8 de septiembre de 2019 2:40