SQL - Anular importes duplicados

 
Vista:
sin imagen de perfil
Val: 12
Ha aumentado 1 puesto en SQL (en relación al último mes)
Gráfica de SQL

Anular importes duplicados

Publicado por Oscar (7 intervenciones) el 24/06/2019 15:02:08
Buenas tardes,

Mi consulta es referente a SQL Server 2016. Simplemente necesito indicaciones de cómo resolver este problema tan común.

Resumiendo, tengo una bbdd con Presupuestos:

PPTOS

Otra con los Repuestos utilizados en cada Presupuesto:

REPUESTOS

Sencillo código:

SELECT
PPTO, TOTAL, REPUESTO

FROM PRESUPUESTOS T1

LEFT JOIN REPUESTOS T2 on T2.PPTO = T1.PPTO


Y el resultado esperado por el JOIN. La idea es que el Total del registro #3 aparezca como NULL en lugar de arrastrar el mismo valor, pues en un sumatorio desvirtuará los resultados.

RESULTADO

Muchas gracias por orientarme.

Slds.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Vega
Val: 187
Ha mantenido su posición en SQL (en relación al último mes)
Gráfica de SQL

Anular importes duplicados

Publicado por Vega (73 intervenciones) el 24/06/2019 16:02:17
Hola Oscar,
¿los presupuestos (PPTO) tienen una fecha de creación?
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 12
Ha aumentado 1 puesto en SQL (en relación al último mes)
Gráfica de SQL

Anular importes duplicados

Publicado por Oscar (7 intervenciones) el 24/06/2019 21:04:13
Hola Vega,

Sí, pero para el caso es indiferente porque pueden tener la misma. De hecho en el ejemplo que he puesto todos tenían la misma.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Vega
Val: 187
Ha mantenido su posición en SQL (en relación al último mes)
Gráfica de SQL

Anular importes duplicados

Publicado por Vega (73 intervenciones) el 24/06/2019 21:27:46
Pero tendrás algún campo en algún sitio que te indique la cardinalidad del registro, ¿No? Sino, creo que lo llevas chungo :)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 12
Ha aumentado 1 puesto en SQL (en relación al último mes)
Gráfica de SQL

Anular importes duplicados

Publicado por Oscar (7 intervenciones) el 25/06/2019 21:06:00
La cardinalidad la define el Presupuesto y los Repuestos: N:M

En este caso diferentes Presupuestos pueden estar enlazados a diferentes Repuestos y viceversa.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Anular importes duplicados

Publicado por leonardo_josue (1173 intervenciones) el 26/06/2019 17:58:46
Hola Oscar:

Una forma de hacer lo que quieres es con un CASE WHEN... en tu ejemplo no mencionas qué criterio utilizas para identificar qué elemento de los "repetidos" sí debe de trae el total... en este caso voy a suponer que te interesa el PRIMER REPUESTO EN ORDEN ALFABÉTICO. Entonces, tendrías esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> SELECT * FROM presupuestos;
+------+-------+
| ppto | total |
+------+-------+
|  111 |  2300 |
|  112 |  1250 |
|  113 |   256 |
+------+-------+
3 rows in set (0.00 sec)
 
mysql> SELECT * FROM repuestos;
+------+----------+
| ppto | repuesto |
+------+----------+
|  111 | A1       |
|  112 | G3       |
|  112 | G5       |
|  113 | B5       |
+------+----------+
4 rows in set (0.00 sec)

tal como tienes tu consulta, obtienes esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> SELECT
    -> P1.ppto, P1.total, R1.repuesto
    -> FROM presupuestos P1
    -> LEFT JOIN repuestos R1  on P1.ppto = R1.ppto;
+------+-------+----------+
| ppto | total | repuesto |
+------+-------+----------+
|  111 |  2300 | A1       |
|  112 |  1250 | G3       |
|  112 |  1250 | G5       |
|  113 |   256 | B5       |
+------+-------+----------+
4 rows in set (0.00 sec)

Entonces, en lugar de poner directamente el campo TOTAL lo que haces es un CASE-WHEN para preguntar si el repuesto es el PRIMERO EN ORDEN ALFABETICO, si es así, entonces muestras el total, si no es así entonces PUEDES MOSTRAR UN NULL O LO QUE QUIERAS. Sería más o menos así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> SELECT
    ->   R1.ppto,
    ->   CASE WHEN NOT EXISTS ( SELECT *
    ->                          FROM repuestos
    ->                          WHERE repuestos.ppto = R1.ppto
    ->                                and repuestos.repuesto < R1.repuesto)
    ->   THEN p1.total ELSE null END total,
    ->   R1.REPUESTO
    -> FROM presupuestos P1
    -> LEFT JOIN repuestos R1  on P1.PPTO = R1.ppto
    -> ORDER BY P1.ppto, R1.repuesto;
+------+-------+----------+
| ppto | total | REPUESTO |
+------+-------+----------+
|  111 |  2300 | A1       |
|  112 |  1250 | G3       |
|  112 |  NULL | G5       |
|  113 |   256 | B5       |
+------+-------+----------+
4 rows in set (0.01 sec)

Mucho ojo, esta consulta sirve SÓLAMENTE SI NO TIENES NOMBRES DE REPUESTOS DUPLICADOS.

Haz la prueba y nos comentas.

Saludos
Leo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 12
Ha aumentado 1 puesto en SQL (en relación al último mes)
Gráfica de SQL

Anular importes duplicados

Publicado por Oscar (7 intervenciones) el 26/06/2019 21:46:27
Muchas gracias Leonardo, muy ingenioso. Sí que puedo tener repuestos duplicados pero no en el mismo presupuesto.

Qué os parece como alternativa usar la función LAG para leer el registro anterior?

Por ejemplo:

LAG(ppto) OVER (ORDER BY Fecha_ppto) as ppto_Anterior

En caso de encontrar el mismo presupuesto leído anteriormente, ordenados por fecha, muevo NULL
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Anular importes duplicados

Publicado por leonardo_josue (1173 intervenciones) el 27/06/2019 15:56:01
Hola de Nuevo Oscar:

1
Qué os parece como alternativa usar la función LAG para leer el registro anterior?

Pues más bien eres tú quien debe de contestar la pregunta... dinos si te ha funcionado utilizar la función de Agregación LAG y cómo ha quedado la consulta.

Como nota te diría, que la función LAG no está disponible para todos los DBMS's, sino que es propia de SQL Server.

Saludos
Leo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 12
Ha aumentado 1 puesto en SQL (en relación al último mes)
Gráfica de SQL

Anular importes duplicados

Publicado por Oscar (7 intervenciones) el 29/06/2019 21:50:04
Pues sí, aquí tenéis el nuevo código. Se trata de comparar cada TOTAL con su anterior mediante la
función LAG, combinado con CASE WHEN y el álias total_Anterior.
La ruptura es por presupuesto y el orden por repuesto:

1
2
3
4
5
6
7
8
9
10
11
SELECT PPTO, TOTAL, REPUESTO,
 
CASE WHEN total_Anterior = TOTAL THEN null ELSE TOTAL END as nuevo_total
 
  FROM (SELECT *,
 
  LAG(T1.TOTAL) OVER ( PARTITION BY t1.ppto ORDER BY repuesto) as total_Anterior
 
          FROM PRESUPUESTOS T1
 
          LEFT JOIN REPUESTOS T2 on T2.PPTO = T1.PPTO)  tabla

Resultado:


sql

Slds.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar