none
consulta en sql RRS feed

  • Pregunta

  • Hola!

    tengo dias sin resolver esto, su apoyo porfavor

    se desea que por medio de una consulta muestre un unico registro por codigo concatenando los telefonos y correos que tuvieran con el detalle que no tiene que concatenar si estos valores estan repetidos.

    un ejemplo de la data

    codigo |nombre|telefono correo
    ---------------------------------------------
    100 |juan  |123 |
    ---------------------------------------------
    101 |pedro  |456  |pedro@a.com
    ---------------------------------------------
    101 |pedro  |456 |pedro@b.com
    ---------------------------------------------
    102 |michel  |789 |michel@a.com
    ---------------------------------------------
    102 |michel  |111 |michel@b.com
    ---------------------------------------------

    el caso de pedro deberia quedar asi: 101|pedro|456|pedro@a.com, pedro@b.com

    gracias por los minutos de su tiempo en ayudarme en este problema.


    • Editado Edison2019 lunes, 26 de agosto de 2019 22:31 colocacion de ejemplo
    lunes, 26 de agosto de 2019 20:30

Respuestas

  • Hola Edison2019:

    Una de las maneras, es utilizar la función LEAD, que aparece en 2012, para leer los registros siguientes a la fila actual.

    Por ejemplo, en tu escenario.

    DECLARE @codigo INT= 101;
    SELECT source.codigo, 
           source.nombre, 
           source.telefono,
           CASE
               WHEN source.correo IS NULL
               THEN ''
               WHEN source.sig1 IS NULL
               THEN concat(source.correo, ';')
               WHEN source.sig2 IS NULL
               THEN concat(source.correo, ';', source.sig1, ';')
               WHEN source.sig3 IS NULL
               THEN concat(source.correo, ';', source.sig1, ';', source.sig2, ';')
               WHEN source.sig4 IS NULL
               THEN concat(source.correo, ';', source.sig1, ';', source.sig2, ';', source.sig3, ';')
               WHEN source.sig5 IS NULL
               THEN concat(source.correo, ';', source.sig1, ';', source.sig2, ';', source.sig3, ';', source.sig4, ';')
               ELSE concat(source.correo, ';', source.sig1, ';', source.sig2, ';', source.sig3, ';', source.sig4, ';', source.sig5, ';')
           END AS cuenta
    FROM
    (
        SELECT ROW_NUMBER() OVER(PARTITION BY codigo
               ORDER BY nombre) AS row, 
               codigo, 
               correo, 
               nombre, 
               telefono, 
               LEAD(correo, 1, null) OVER(ORDER BY correo) AS sig1, 
               LEAD(correo, 2, null) OVER(ORDER BY correo) AS sig2, 
               LEAD(correo, 3, null) OVER(ORDER BY correo) AS sig3, 
               LEAD(correo, 4, null) OVER(ORDER BY correo) AS sig4, 
               LEAD(correo, 5, null) OVER(ORDER BY correo) AS sig5
        FROM correos
        WHERE codigo = @codigo
    ) AS source
    WHERE row = 1;

    Aunque seguro que existen muchas otras, pero esta te devuelve los resultados, para 6 cuentas, y es de lo más fácil de implementar y de comprender.

    LEAD

    https://javifer2.wordpress.com/2018/09/11/lag-y-lead-siguiente-y-anterior/

    Espero te sirva



    • Marcado como respuesta Edison2019 martes, 27 de agosto de 2019 19:21
    martes, 27 de agosto de 2019 17:25

Todas las respuestas

  • ¿Y el ejemplo de la data?, ¿Que version de SQL Server maneja?

    IIslas Master Consultant SQL Server

    lunes, 26 de agosto de 2019 20:31
  • codigo |nombre |telefono correo
    ---------------------------------------------
    100 |juan |123 |
    ---------------------------------------------
    101 |pedro |456  |pedro@a.com
    ---------------------------------------------
    101 |pedro |456 |pedro@b.com
    ---------------------------------------------
    102 |michel |789 |michel@a.com
    ---------------------------------------------
    102 |michel |111 |michel@b.com
    ---------------------------------------------
    lunes, 26 de agosto de 2019 21:55
  • version 2017
    lunes, 26 de agosto de 2019 21:56
  • Hola Edison2019:

    En 2017 dispones de String_agg para realizar esta tarea

    CREATE TABLE correos
    (codigo   INT, 
     nombre   VARCHAR(15), 
     telefono VARCHAR(3), 
     correo   VARCHAR(18)
    );
    GO
    insert into correos (codigo, nombre, telefono, correo)
    values
    (100,'juan','123',null),
    (101,'pedro','456','pedro@a.com'),
    (101,'pedro','456','pedro@b.com'),
    (102,'michel','789','michel@a.com'),
    (102,'michel','111','michel@b.com');
    go
    declare @codigo int = 101;
    
    SELECT correos.codigo, 
           correos.nombre, 
           correos.telefono,
    	  string_agg (correo,',') as cuenta
    FROM correos 
      
    where correos.codigo = @codigo
    group by codigo, nombre, telefono
    

    Salida


    String_Agg

    https://docs.microsoft.com/es-es/sql/t-sql/functions/string-agg-transact-sql?view=sql-server-2017

    martes, 27 de agosto de 2019 4:01
  • Muchas gracias Javi Fernandez; tu solución es estupenda con la version 2017; desdichadamente la he subido al servidor y grande ha sido mi sorpresa al ver que es 2012 T_T

    Select @@version

    Microsoft SQL Server 2012 (SP4-GDR) (KB4057116) - 11.0.7462.6 (Intel X86)   Jan  5 2018 22:11:41   Copyright (c) Microsoft Corporation  Standard Edition on Windows NT 6.3 <X64> (Build 9600: ) (WOW64) (Hypervisor) 

    alguna solucion similar para esta version, he googleado pero no hallo con la respuesta.

    gracias!

    Edison

    martes, 27 de agosto de 2019 15:30
  • Hola Edison2019:

    Una de las maneras, es utilizar la función LEAD, que aparece en 2012, para leer los registros siguientes a la fila actual.

    Por ejemplo, en tu escenario.

    DECLARE @codigo INT= 101;
    SELECT source.codigo, 
           source.nombre, 
           source.telefono,
           CASE
               WHEN source.correo IS NULL
               THEN ''
               WHEN source.sig1 IS NULL
               THEN concat(source.correo, ';')
               WHEN source.sig2 IS NULL
               THEN concat(source.correo, ';', source.sig1, ';')
               WHEN source.sig3 IS NULL
               THEN concat(source.correo, ';', source.sig1, ';', source.sig2, ';')
               WHEN source.sig4 IS NULL
               THEN concat(source.correo, ';', source.sig1, ';', source.sig2, ';', source.sig3, ';')
               WHEN source.sig5 IS NULL
               THEN concat(source.correo, ';', source.sig1, ';', source.sig2, ';', source.sig3, ';', source.sig4, ';')
               ELSE concat(source.correo, ';', source.sig1, ';', source.sig2, ';', source.sig3, ';', source.sig4, ';', source.sig5, ';')
           END AS cuenta
    FROM
    (
        SELECT ROW_NUMBER() OVER(PARTITION BY codigo
               ORDER BY nombre) AS row, 
               codigo, 
               correo, 
               nombre, 
               telefono, 
               LEAD(correo, 1, null) OVER(ORDER BY correo) AS sig1, 
               LEAD(correo, 2, null) OVER(ORDER BY correo) AS sig2, 
               LEAD(correo, 3, null) OVER(ORDER BY correo) AS sig3, 
               LEAD(correo, 4, null) OVER(ORDER BY correo) AS sig4, 
               LEAD(correo, 5, null) OVER(ORDER BY correo) AS sig5
        FROM correos
        WHERE codigo = @codigo
    ) AS source
    WHERE row = 1;

    Aunque seguro que existen muchas otras, pero esta te devuelve los resultados, para 6 cuentas, y es de lo más fácil de implementar y de comprender.

    LEAD

    https://javifer2.wordpress.com/2018/09/11/lag-y-lead-siguiente-y-anterior/

    Espero te sirva



    • Marcado como respuesta Edison2019 martes, 27 de agosto de 2019 19:21
    martes, 27 de agosto de 2019 17:25
  • Otras opciones, son la realizacion de pivot.

    Un ejemplo del más fácil.

    DECLARE @codigo INT= 101;
    SELECT pvt.codigo, pvt.nombre, pvt.telefono,
    CASE
               WHEN pvt.[1] IS NULL
               THEN ''
               WHEN pvt.[2] IS NULL
               THEN concat(pvt.[1], ';')
               WHEN pvt.[3] IS NULL
               THEN concat(pvt.[1], ';', pvt.[2], ';')
               WHEN  pvt.[4]IS NULL
               THEN concat(pvt.[1], ';', pvt.[2], ';', pvt.[3], ';')
               WHEN  pvt.[5] IS NULL
               THEN concat(pvt.[1], ';', pvt.[2], ';', pvt.[3], ';', pvt.[4], ';')
               WHEN  pvt.[6] IS NULL
               THEN concat(pvt.[1], ';', pvt.[2], ';', pvt.[3], ';', pvt.[4], ';', pvt.[5], ';')
               ELSE concat(pvt.[1], ';', pvt.[2], ';', pvt.[3], ';', pvt.[4], ';', pvt.[5], ';', pvt.[6], ';')
           END AS cuenta
    
    FROM
    (
        SELECT ROW_NUMBER() OVER(PARTITION BY codigo
               ORDER BY nombre) AS row, 
               codigo, 
               correo, 
               nombre, 
               telefono
           
        FROM correos
        WHERE codigo = @codigo
    ) AS source
    pivot (max(correo) for row in([1], [2], [3],[4],[5], [6])) as pvt

    Pivot

    https://javifer2.blogspot.com/search/label/pivot

    También se puede realizar un pivot dinámico, para no estar limitado a x correos, pero es un poco más complicado.

    martes, 27 de agosto de 2019 17:35
  • Maestro, gracias por la solución; adapte el script y funciona.

    gracias Maestro

    martes, 27 de agosto de 2019 19:29