none
Crear vista eliminando duplicados RRS feed

  • Pregunta

  • Buenas,

    Llevo unos días peleandome con una vista y no soy capaz de que muestre lo que yo quiero.

    Imaginemos una tabla denominada tbReparación y otra denominada tbArtículos.

    Cada reparación puede tener asociados varios artículos, de los cuales algunos pueden ser facturables o no.
    También puede haber reparaciones que no tengan ningún articulo.

    Necesito crear una vista en donde visualice todas las reparaciones y un booleano que indique si alguno de los artículos pertenecientes a dicha reparación contuviese un articulo facturable.



    Lo que consigo es una linea por cada articulo en vez de una linea por cada reparación (duplicando reparaciones)...

    tbReparacion
    IDRep
    1
    2
    3
    4
    5

    tbArticulo
    IDArt     -     Fact
    1             -     0
    2             -     1
    3             -     1
    4             -     0
    5             -     1

    tbImputaciones
    IDImp - IDRep - IDArt
    1          -      2    -         5
    2          -      3    -         1
    3          -      3    -         3
    4          -      4    -         1
    5          -      5    -         2 


    Vista deseada:

    idRep Fact
    1 0 /* no tiene ningún artículo imputado*/
    2 1 /* tiene imputado el artículo 5 que es facturable*/
    3 1 /* tiene dos artículos imputados de los cuales 1 es facturable*/
    4 0 /* tiene imputado el articulo 1 que no es facturable*/
    5 1 /* tiene imputado el articulo 2 que es facturable

    viernes, 25 de enero de 2019 16:00

Todas las respuestas

  • A ver si te gusta esta solucion. Para entenderla, recuerda que el count(columna) no cuenta los nulls.

    create table tbReparacion (IDRep int)
    Insert tbReparacion values (1),(2),(3),(4),(5)
    go
    
    create table tbArticulo(IDArt int, Fact int)
    insert tbArticulo values (1, 0), (2, 1), (3, 1), (4, 0), (5, 1)
    go
    
    create table tbImputaciones(IDImp int, IDRep int, IDArt int)
    insert tbImputaciones values (1, 2, 5), (2, 3, 1), (3, 3, 3), (4, 4, 1), (5, 5, 2 )
    go
    
    select r.idRep, count(a.Fact) as Fact from
    tbReparacion as r
    left join tbImputaciones as i on r.IDRep=i.IDRep
    left join tbArticulo as a on a.IDArt=i.IDArt and a.Fact<>0
    group by r.IdRep

    • Propuesto como respuesta Pedro Alfaro viernes, 25 de enero de 2019 16:43
    viernes, 25 de enero de 2019 16:23
  • Muchisimas gracias, funcionó a la perfección.

    Entiendo que si hay más de un artículo facturable en la misma reparación irá aumentando 'Fact' ¿verdad?

    No entiendo muy bien el funcionamiento (Noob)...

    Viasualizamos el número de reparación y el contador Fact de los articulos. 

    Para ello cogemos la tabla de reparaciones y la cruzamos con la de imputaciones mediante el IDRep.

    A su vez, cogemos dicho cruce y lo cruzamos con la tabla de articulos que sean facturables (Fact<>0) a través del IDArt.

    Agrupamos por Reparacion....

    No lo pillo 😫


    viernes, 25 de enero de 2019 18:22
  • Vamos que ya estas cerca.

    La clave de la solucion de Alberto radica en usar outer joins y asi preservar la tabla reparaciones y poder ver todas sus filas aunque no tenga asociada un articulo que sea facturable.  Recuerda que en un outer join el lado que no se preserva contendra la marca NULL en las columnas referenciadas si no hay una fila que mache de ese lado y la marca NULL no hes considerada por funciones de agrupacion.

    Veamos el resultado de esa sentencia sin agrupar:

    reparacion  imputacion  articulo  fact
    1               null             null       null  -- no imputacion
    2               1                5           1
    3               2                null        null  -- no articulo facturable
    3               3                3           1
    4               4                null        null  -- no articulo facturable
    5               5                2           1

    IDRep	IDImp	IDArt	Fact
    1	NULL	NULL	NULL
    2	1	5	1
    3	2	NULL	NULL
    3	3	3	1
    4	4	NULL	NULL
    5	5	2	1


    Ahora agrupa y cuenta por cuantas filas por reparacion tienen valor.  La marca NULL no sera contemplada en el conteo pera a la final aquellas sin imputacion o articulo facturable alguno tendran cero por asi contamos (0, 1, ...).

    reparacion conteo
    1              0
    2              1
    3              1
    4              0
    5              1

    Otra forma seria preservando solo la tabla tbReparacion y no la de imputaciones.

    SELECT
        r.IDRep,
        i.IDImp,
        a.IDArt,
        a.Fact
    FROM
        tbReparacion as r
        
        LEFT JOIN
        (
        tbImputaciones as i 
           
        INNER JOIN
        tbArticulo as a 
        ON a.IDArt=i.IDArt 
        AND a.Fact = 1
        )
        ON r.IDRep=i.IDRep
    ;
    
    
    IDRep	IDImp	IDArt	Fact
    1	NULL	NULL	NULL
    2	1	5	1
    3	3	3	1
    4	NULL	NULL	NULL
    5	5	2	1


    AMB

    Some guidelines for posting questions...

    AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas

    viernes, 25 de enero de 2019 20:16
  • Voy viendo la luz...

    Lo que yo conseguía era verlo sin agrupar, una línea por cada imputación duplicándome ordenes.

    ¿La condición a.Fact<>0 del ejemplo de Alberto por qué es necesaria?

    Yo entiendo que si cruzo las tablas, cuento cada Fact y agrupo debería funcionar sin esa condición...

    sábado, 26 de enero de 2019 8:37
  • ¿La condición a.Fact<>0 del ejemplo de Alberto por qué es necesaria?

    La condición está metida en el ON del LEFT JOIN para que genere un NULL en los registros que no la cumplan. De esa manera, al hacer el Count esos registros no se cuentan, y gracias a eso el count saca el número de los articulos que tenian un valor distinto de cero en Fact.

    Desde luego, no es esa la única forma de conseguir el resultado deseado. Por ejemplo, otra forma en la que lo podrías hacer es usando un SUM en lugar del COUNT, aprovechando que FACT vale 1 ó 0, por lo que la suma seria igual al número de unos. En ese caso no necesitarías la condición a.Fact<>0.

    • Propuesto como respuesta Pedro Alfaro lunes, 28 de enero de 2019 23:17
    sábado, 26 de enero de 2019 8:58