none
Separar una columna en dos columnas RRS feed

Respuestas

  • Hola L - J - R:

    ¿se puede lograr?

    La respuesta es si.

    Como el escenario que planteas es muy difuso, te doy una solución por pasos.

    Para empezar la información la voy a cargar en una tabla. Y voy a utilizar ctes correlativos, para ir solucionando los problemas. Además de la función row_Number para numerar filas.

    create table dbo.source(columnaPrincipal varchar(100));
    go
    Insert into dbo.source (columnaPrincipal)
    values
    ('Dato1'),
    ('Dato2'),
    ('Dato3'),
    ('Dato4'),
    ('Dato5');

    Ya tenemos la información. Te iré mostrando la solución por pasos, para al final, darla completa.

    with c1 as (
    	
    	Select *
    		, ROW_NUMBER() over(order by (Select null)) as rn
    	from dbo.source
    	)select * from c1


    Numeramos las filas. Ahora necesitamos saber cuantas filas tiene el origen.

    with c1 as (
    	
    	Select *
    		, ROW_NUMBER() over(order by (Select null)) as rn
    	from dbo.source
    	)
    	, c2 as (
    	Select count(*) as numRecords 
    	from c1
    	)select * from c2

    En el conjunto c2, por tanto tenemos un numRecords=5

    with c1 as (
    	
    	Select *
    		, ROW_NUMBER() over(order by (Select null)) as rn
    	from dbo.source
    	)
    	, c2 as (
    	Select count(*) as numRecords 
    	from c1
    	),c3 as (
    	select * 
    		from c1 cross join c2 
    			where c1.rn <= ((c2.numRecords/2) 
    				+ case when c2.numRecords%2=0 then 0 else 1 end )
    	)
    	Select * from c3

    Por tanto en c3 tenemos la mitad de las filas. Con el case, evaluamos si el resto de la división del número de filas es 0, entonces serán todas las filas cuyo rn sea menor o igual a la división del total entre dos. Pero sino como es el caso, será la división entre 2 + 1.

    with c1 as (
    	
    	Select *
    		, ROW_NUMBER() over(order by (Select null)) as rn
    	from dbo.source
    	)
    	, c2 as (
    	Select count(*) as numRecords 
    	from c1
    	),c3 as (
    	select * 
    		from c1 cross join c2 
    			where c1.rn <= ((c2.numRecords/2) 
    				+ case when c2.numRecords%2=0 then 0 else 1 end )
    	),c4 as (
    	select *, ROW_NUMBER() over(order by rn) as rnCol2 from c1 cross join c2  
    		where c1.rn > ((c2.numRecords/2)+ case when c2.numRecords%2=0 then 0 else 1 end )
    	)select * from c4

    Ahora ocurre lo mismo en el criterio de exclusión de las filas, pero recogiendo solo las que rn sea mayor.

    Por otro lado para poder unir el conjunto anterior y este, utilizamos row_number y así tenemos estas columnas para unir los conjuntos.

    with c1 as (
    	
    	Select *
    		, ROW_NUMBER() over(order by (Select null)) as rn
    	from dbo.source
    	)
    	, c2 as (
    	Select count(*) as numRecords 
    	from c1
    	),c3 as (
    	select * 
    		from c1 cross join c2 
    			where c1.rn <= ((c2.numRecords/2) 
    				+ case when c2.numRecords%2=0 then 0 else 1 end )
    	),c4 as (
    	select *, ROW_NUMBER() over(order by rn) as rnCol2 from c1 cross join c2  
    		where c1.rn > ((c2.numRecords/2)+ case when c2.numRecords%2=0 then 0 else 1 end )
    	)
    	select c3.columnaPrincipal as columna1, 
    			isnull(c4.columnaPrincipal,'') as columna2 
    		from c3 left join c4 on c3.rn = c4.rnCol2

    El resultado es el solicitado. Aplicando la función isnull, para la columna2.

    Cte correlativo

    https://javifer2.wordpress.com/2018/12/18/with-cte-tablas-de-expresion-comun-2-correlativos/

    Row Number

    https://javifer2.wordpress.com/2019/11/11/row-number-numerar-filas/

    isNull

    https://javifer2.wordpress.com/2019/11/17/isnull-una-de-las-funciones-mas-usadas/

    • Marcado como respuesta L - J - R jueves, 29 de julio de 2021 18:12
    jueves, 29 de julio de 2021 6:16
  • Hola:

    No das indicaciones de como tienes los datos, ni cuantas filas/columnas tienes, etc... pero poderse se puede hacer. Te pongo un ejemplo a ver si te sirve.

    DECLARE @NumRows INT = 3	/* DECLARAMOS CUANTAS FILAS QUEREMOS VER EN LA TABLA FINAL */
    
    ;WITH TusDatos AS (
    	SELECT TOP (@NumRows * 3 - 1) -- Truco, vamos a extraer datos para rellenar 3 columnas ;-)
    		/* Con éstas 2 columnas 'numeramos' los registros para realizar luego agrupacion. 
    		Nota: Tienes que cambiar Object_Id por el campo de tus datos correspondiente)
    		*/
    		CAST(((ROW_NUMBER() OVER(order by object_id) -1)/ @NumRows) AS INT) + 1 as GroupN,
    		(ROW_NUMBER() OVER(order by object_id) - 1) % @NumRows  + 1 as NumRow,
    	/* Aqui has de poner tu SELECT, yo he cogido (n) registros de sys.objects */
    		name FROM sys.objects
    ), NumRows AS (
    	/* Aquí simplemente tenemos una SELECT para 'crear' el numero de registros que queremos ver */
    	SELECT TOP (@NumRows) ROW_NUMBER() OVER(order by object_id) as NumRow from sys.objects
    )
    SELECT
    	/*Obviamente, tendras que poner tantas columnas como tus datos necesiten.*/
    	STRING_AGG(CASE WHEN TusDatos.GroupN = 1 THEN TusDatos.name ELSE '' END, '') AS COL1,
    	STRING_AGG(CASE WHEN TusDatos.GroupN = 2 THEN TusDatos.name ELSE '' END, '') AS COL2,
    	STRING_AGG(CASE WHEN TusDatos.GroupN = 3 THEN TusDatos.name ELSE '' END, '') AS COL3
    	/*Obviamente, tendras que poner tantas columnas como tus datos necesiten.*/
      FROM	NumRows JOIN TusDatos on NumRows.NumRow = TusDatos.NumRow
      GROUP BY NumRows.NumRow
    	

    Está comentado dentro del código, espero haberlo explicado bien.

    Un saludo

    • Marcado como respuesta L - J - R jueves, 29 de julio de 2021 18:12
    jueves, 29 de julio de 2021 6:55
  • Mi solución (solo por divertirme):

    With cteBase As
    (
    select ColumnaPrincipal, NTILE(2) OVER(ORDER BY ColumnaPrincipal) AS Columna from tabla
    )
    SELECT s1.ColumnaPrincipal, s2.ColumnaPrincipal FROM
    (Select *, ROW_NUMBER() OVER(Partition by Columna ORDER BY ColumnaPrincipal) as Id FROM cteBase WHERE columna=1) AS S1
    LEFT JOIN 
    (Select *, ROW_NUMBER() OVER(Partition by Columna ORDER BY ColumnaPrincipal) as Id FROM cteBase WHERE columna=2) AS S2
    ON S1.Id = S2.Id

    • Marcado como respuesta L - J - R jueves, 29 de julio de 2021 18:12
    jueves, 29 de julio de 2021 13:49

Todas las respuestas

  • Hola L - J - R:

    ¿se puede lograr?

    La respuesta es si.

    Como el escenario que planteas es muy difuso, te doy una solución por pasos.

    Para empezar la información la voy a cargar en una tabla. Y voy a utilizar ctes correlativos, para ir solucionando los problemas. Además de la función row_Number para numerar filas.

    create table dbo.source(columnaPrincipal varchar(100));
    go
    Insert into dbo.source (columnaPrincipal)
    values
    ('Dato1'),
    ('Dato2'),
    ('Dato3'),
    ('Dato4'),
    ('Dato5');

    Ya tenemos la información. Te iré mostrando la solución por pasos, para al final, darla completa.

    with c1 as (
    	
    	Select *
    		, ROW_NUMBER() over(order by (Select null)) as rn
    	from dbo.source
    	)select * from c1


    Numeramos las filas. Ahora necesitamos saber cuantas filas tiene el origen.

    with c1 as (
    	
    	Select *
    		, ROW_NUMBER() over(order by (Select null)) as rn
    	from dbo.source
    	)
    	, c2 as (
    	Select count(*) as numRecords 
    	from c1
    	)select * from c2

    En el conjunto c2, por tanto tenemos un numRecords=5

    with c1 as (
    	
    	Select *
    		, ROW_NUMBER() over(order by (Select null)) as rn
    	from dbo.source
    	)
    	, c2 as (
    	Select count(*) as numRecords 
    	from c1
    	),c3 as (
    	select * 
    		from c1 cross join c2 
    			where c1.rn <= ((c2.numRecords/2) 
    				+ case when c2.numRecords%2=0 then 0 else 1 end )
    	)
    	Select * from c3

    Por tanto en c3 tenemos la mitad de las filas. Con el case, evaluamos si el resto de la división del número de filas es 0, entonces serán todas las filas cuyo rn sea menor o igual a la división del total entre dos. Pero sino como es el caso, será la división entre 2 + 1.

    with c1 as (
    	
    	Select *
    		, ROW_NUMBER() over(order by (Select null)) as rn
    	from dbo.source
    	)
    	, c2 as (
    	Select count(*) as numRecords 
    	from c1
    	),c3 as (
    	select * 
    		from c1 cross join c2 
    			where c1.rn <= ((c2.numRecords/2) 
    				+ case when c2.numRecords%2=0 then 0 else 1 end )
    	),c4 as (
    	select *, ROW_NUMBER() over(order by rn) as rnCol2 from c1 cross join c2  
    		where c1.rn > ((c2.numRecords/2)+ case when c2.numRecords%2=0 then 0 else 1 end )
    	)select * from c4

    Ahora ocurre lo mismo en el criterio de exclusión de las filas, pero recogiendo solo las que rn sea mayor.

    Por otro lado para poder unir el conjunto anterior y este, utilizamos row_number y así tenemos estas columnas para unir los conjuntos.

    with c1 as (
    	
    	Select *
    		, ROW_NUMBER() over(order by (Select null)) as rn
    	from dbo.source
    	)
    	, c2 as (
    	Select count(*) as numRecords 
    	from c1
    	),c3 as (
    	select * 
    		from c1 cross join c2 
    			where c1.rn <= ((c2.numRecords/2) 
    				+ case when c2.numRecords%2=0 then 0 else 1 end )
    	),c4 as (
    	select *, ROW_NUMBER() over(order by rn) as rnCol2 from c1 cross join c2  
    		where c1.rn > ((c2.numRecords/2)+ case when c2.numRecords%2=0 then 0 else 1 end )
    	)
    	select c3.columnaPrincipal as columna1, 
    			isnull(c4.columnaPrincipal,'') as columna2 
    		from c3 left join c4 on c3.rn = c4.rnCol2

    El resultado es el solicitado. Aplicando la función isnull, para la columna2.

    Cte correlativo

    https://javifer2.wordpress.com/2018/12/18/with-cte-tablas-de-expresion-comun-2-correlativos/

    Row Number

    https://javifer2.wordpress.com/2019/11/11/row-number-numerar-filas/

    isNull

    https://javifer2.wordpress.com/2019/11/17/isnull-una-de-las-funciones-mas-usadas/

    • Marcado como respuesta L - J - R jueves, 29 de julio de 2021 18:12
    jueves, 29 de julio de 2021 6:16
  • Hola:

    No das indicaciones de como tienes los datos, ni cuantas filas/columnas tienes, etc... pero poderse se puede hacer. Te pongo un ejemplo a ver si te sirve.

    DECLARE @NumRows INT = 3	/* DECLARAMOS CUANTAS FILAS QUEREMOS VER EN LA TABLA FINAL */
    
    ;WITH TusDatos AS (
    	SELECT TOP (@NumRows * 3 - 1) -- Truco, vamos a extraer datos para rellenar 3 columnas ;-)
    		/* Con éstas 2 columnas 'numeramos' los registros para realizar luego agrupacion. 
    		Nota: Tienes que cambiar Object_Id por el campo de tus datos correspondiente)
    		*/
    		CAST(((ROW_NUMBER() OVER(order by object_id) -1)/ @NumRows) AS INT) + 1 as GroupN,
    		(ROW_NUMBER() OVER(order by object_id) - 1) % @NumRows  + 1 as NumRow,
    	/* Aqui has de poner tu SELECT, yo he cogido (n) registros de sys.objects */
    		name FROM sys.objects
    ), NumRows AS (
    	/* Aquí simplemente tenemos una SELECT para 'crear' el numero de registros que queremos ver */
    	SELECT TOP (@NumRows) ROW_NUMBER() OVER(order by object_id) as NumRow from sys.objects
    )
    SELECT
    	/*Obviamente, tendras que poner tantas columnas como tus datos necesiten.*/
    	STRING_AGG(CASE WHEN TusDatos.GroupN = 1 THEN TusDatos.name ELSE '' END, '') AS COL1,
    	STRING_AGG(CASE WHEN TusDatos.GroupN = 2 THEN TusDatos.name ELSE '' END, '') AS COL2,
    	STRING_AGG(CASE WHEN TusDatos.GroupN = 3 THEN TusDatos.name ELSE '' END, '') AS COL3
    	/*Obviamente, tendras que poner tantas columnas como tus datos necesiten.*/
      FROM	NumRows JOIN TusDatos on NumRows.NumRow = TusDatos.NumRow
      GROUP BY NumRows.NumRow
    	

    Está comentado dentro del código, espero haberlo explicado bien.

    Un saludo

    • Marcado como respuesta L - J - R jueves, 29 de julio de 2021 18:12
    jueves, 29 de julio de 2021 6:55
  • Mi solución (solo por divertirme):

    With cteBase As
    (
    select ColumnaPrincipal, NTILE(2) OVER(ORDER BY ColumnaPrincipal) AS Columna from tabla
    )
    SELECT s1.ColumnaPrincipal, s2.ColumnaPrincipal FROM
    (Select *, ROW_NUMBER() OVER(Partition by Columna ORDER BY ColumnaPrincipal) as Id FROM cteBase WHERE columna=1) AS S1
    LEFT JOIN 
    (Select *, ROW_NUMBER() OVER(Partition by Columna ORDER BY ColumnaPrincipal) as Id FROM cteBase WHERE columna=2) AS S2
    ON S1.Id = S2.Id

    • Marcado como respuesta L - J - R jueves, 29 de julio de 2021 18:12
    jueves, 29 de julio de 2021 13:49
  • Muchas gracias a todos!
     es de gran ayuda e entendible su aportación, logrando resolver mi inquietud. 
    jueves, 29 de julio de 2021 18:14