sábado, 26 de abril de 2008

DESCOMPONER LISTA CSV EN REGISTROS


Esta idea, está basada en una genialidad de Itzik Ben-Gan, MVP de Sql Server. Si quereis ver el hilo de donde saqué el código original : http://groups.google.es/group/microsoft.public.es.sqlserver/browse_thread/thread/488acae128396270/252b881f6ea6a573?lnk=gst&q=BEN+GAN#252b881f6ea6a573

-- La clausula parameters la situamos al inicio de este lote, por exigencias del
-- Editor Sql 1.1, pero de hecho corresponde a la consulta de selección.
-- En 'Cadena' debemos escribir una lista separada por comas : ','
PARAMETERS Cadena Text (255);

-- Creamos una tabla con números de 0 a 9 :
Create Table Nums (Num Long Primary Key);
Insert Into Nums Values (0);
Insert Into Nums Values (1);
Insert Into Nums Values (2);
Insert Into Nums Values (3);
Insert Into Nums Values (4);
Insert Into Nums Values (5);
Insert Into Nums Values (6);
Insert Into Nums Values (7);
Insert Into Nums Values (8);
Insert Into Nums Values (9);

SELECT Número,
Mid(Cadena,Número+1,Abs(InStr(Número+1,Cadena,",")-Número-1))
FROM
(
Select (TNums_2.Número*10) + Nums.Num As Número
From
(
Select (TNums_1.Num*10) + Nums.Num As Número
From Nums, Nums As TNums_1
) As TNums_2, Nums
) AS TNums_3
WHERE Número<=Len(Cadena) And (Número <> 0 Imp Mid(Cadena,Número,1)=",");

DROP TABLE Nums;

Veamos una aplicación práctica : Separar el contenido de un campo de texto, en tantos campos como palabras compongan dicho campo. Es decir, se trata de algo parecido a las consultas para separar nombre y apellidos, pero en este caso, el número de campos, puesto que se trata de una consulta de referencias cruzadas, no es fijo sino variable. Emplearemos como carácter delimitador de las palabras el 'espacio', y basaremos nuestra consulta en el campo 'NombreContacto' de la tabla 'Clientes' de Neptuno.mdb. Además, puesto que Access no permite crear una consulta de unión no basada en tabla alguna (ver ejemplo de Itzik), también será preciso disponer de una tabla (Nums) con valores entre 0 y 9 :

Create Table Nums (Num Long Primary Key);

Insert Into Nums Values (0);
Insert Into Nums Values (1);
Insert Into Nums Values (2);
Insert Into Nums Values (3);
Insert Into Nums Values (4);
Insert Into Nums Values (5);
Insert Into Nums Values (6);
Insert Into Nums Values (7);
Insert Into Nums Values (8);
Insert Into Nums Values (9);

TRANSFORM
First(Mid(NombreContacto,Número,InStr(Número,NombreContacto & " "," ")-Número))
SELECT NombreContacto
FROM
(
Select (TNums_2.Número*10)+ Nums.Num + 1 As Número
From
(
Select (TNums_1.Num*10)+ Nums.Num As Número
From Nums, Nums As TNums_1
) As TNums_2, Nums
) AS TNums_3, Clientes
WHERE
Número<=Len(NombreContacto) And Mid(" " & NombreContacto,Número,1) = " "
GROUP BY NombreContacto
PIVOT
"Segmento_" & Número-Len(Replace(Left(NombreContacto,Número)," ",""))+1;

DROP TABLE Nums;

Otro ejemplo al hilo de las News. En este caso se trata de descomponer la lista embebida dentro del campo de texto, y repetir el mismo registro tantas veces como items tenga la susodicha lista :
http://groups.google.es/group/microsoft.public.es.access/browse_thread/thread/104f793a9ee8fd1e/ce28ad0e5aa2133b?lnk=raot#ce28ad0e5aa2133b

Create Table Nums (Num Long Primary Key);

Insert Into Nums Values (0);
Insert Into Nums Values (1);
Insert Into Nums Values (2);
Insert Into Nums Values (3);
Insert Into Nums Values (4);
Insert Into Nums Values (5);
Insert Into Nums Values (6);
Insert Into Nums Values (7);
Insert Into Nums Values (8);
Insert Into Nums Values (9);

Create Table tbl_musica (Id Counter, Artista Text (255));

Insert Into tbl_musica (Artista) Values ('Pepe/Juan/Paco/Roberto');
Insert Into tbl_musica (Artista) Values ('Gema');
Insert Into tbl_musica (Artista) Values ('Ramon/Juan/Pepito/Roberto');
Insert Into tbl_musica (Artista) Values ('Irene/Juan/Paco/Roberto');
Insert Into tbl_musica (Artista) Values ('Alex/Juan/Paco/Roberto/Alejandro');
Insert Into tbl_musica (Artista) Values ('Curro Romero');

SELECT Id, Num, Mid(Artista,Num+1,Abs(InStr(Num+1,Artista & "/","/")-Num-1))
FROM
(
Select (TNums_1.Num*10)+ Nums.Num As Num
From Nums, Nums As TNums_1
) AS TNums_2, tbl_musica
WHERE Num<=Len(Artista) And (Mid(Artista,IIf(Num=0,1,Num),1) = "/" Or Num=0);

DROP TABLE tbl_musica;
DROP TABLE Nums;

Puesto que las cadenas contenidas en el campo de texto son cortas, he usado una combinación que solo devuelve valores numéricos entre 0 y 100.

Ramon Poch. Terrassa a 19/01/2007.