2011-04-29 17 views
5

Tengo un campo varchar(max) que contiene pares de nombre y valor, en cada línea tengo el valor de nombre debajo de la puntuación.Cómo analizar una cadena y crear varias columnas a partir de ella?

tengo que hacer una consulta contra ella para que devuelva el nombre, los pares de valor en dos columnas (por lo que mediante el análisis del texto, eliminar el subrayado y la "nueva línea" char.

Así que desde este

select NameValue from Table 

donde consigo este texto:

Name1_Value1 
Name2_Value2 
Name3_Value3 

me gustaría tener esta salida

Names Values 
===== ====== 
Name1 Value1 
Name2 Value2 
Name3 Value3 
+0

que cerrar esta pregunta desde que pedí uno nuevo que está más cerca de mi verdadero problema: http://stackoverflow.com/questions/5830065/how-to-query-a -single-memo-field-to-obtain-many-results-one-line – LaBracca

+0

No es necesario cerrar. Puede editar sus preguntas –

+0

Sí, tiene razón, ¡realmente tenía prisa! – LaBracca

Respuesta

6
SELECT substring(NameValue, 1, charindex('_', NameValue)-1) AS Names, 
    substring(NameValue, charindex('_', NameValue)+1, LEN(NameValue)) AS Values 
FROM Table 

EDITAR: Algo como esto puesto en una función o procedimiento almacenado en combinación con una tabla temporal debe trabajar por más de una línea, dependiendo de la línea delimitador también se debe eliminar CHAR(13) antes de empezar:

DECLARE @helper varchar(512) 
DECLARE @current varchar(512) 
SET @helper = NAMEVALUE 
WHILE CHARINDEX(CHAR(10), @helper) > 0 BEGIN 
    SET @current = SUBSTRING(@helper, 1, CHARINDEX(CHAR(10), NAMEVALUE)-1) 
    SELECT SUBSTRING(@current, 1, CHARINDEX('_', @current)-1) AS Names, 
     SUBSTRING(@current, CHARINDEX('_', @current)+1, LEN(@current)) AS Names 
    SET @helper = SUBSTRING(@helper, CHARINDEX(CHAR(10), @helper)+1, LEN(@helper)) 
END 
SELECT SUBSTRING(@helper, 1, CHARINDEX('_', @helper)-1) AS Names, 
    SUBSTRING(@helper, CHARINDEX('_', @helper)+1, LEN(@helper)) AS Names 
+0

Esto funcionará para una línea, pero ¿cómo manejar más líneas? – LaBracca

+0

¿Entonces su diseño de base de datos es borken? Si tiene más de una línea, debe hacer esto en una función o procedimiento almacenado. Ver mi edición –

+0

no, lo que tengo que hacer es una especie de trabajo temporal para simular nuevos campos que no tengo, por supuesto que eliminaré esto tan pronto como tenga tiempo. – LaBracca

1
DECLARE @TExt NVARCHAR(MAX)= '***[ddd]*** 
    dfdf 
    fdfdfdfdfdf 
    ***[fff]*** 
    4545445 
    45454 
    ***[ahaASSDAD]*** 

    DFDFDF 
    ***[SOME TEXT]*** 
    ' 

    DECLARE @Delimiter VARCHAR(1000)= CHAR(13) + CHAR(10) ; 
    WITH numbers 
       AS (SELECT ROW_NUMBER() OVER (ORDER BY o.object_id, o2.object_id) Number 
        FROM  sys.objects o 
          CROSS JOIN sys.objects o2 
       ), 
      c AS (SELECT Number CHARBegin , 
          ROW_NUMBER() OVER (ORDER BY number) RN 
        FROM  numbers 
        WHERE SUBSTRING(@text, Number, LEN(@Delimiter)) = @Delimiter 
       ), 
      res 
       AS (SELECT CHARBegin , 
          CAST(LEFT(@text, charbegin) AS NVARCHAR(MAX)) Res , 
          RN 
        FROM  c 
        WHERE rn = 1 
        UNION ALL 
        SELECT c.CHARBegin , 
          CAST(SUBSTRING(@text, res.CHARBegin, 
              c.CHARBegin - res.CHARBegin) AS NVARCHAR(MAX)) , 
          c.RN 
        FROM  c 
          JOIN res ON c.RN = res.RN + 1 
       ) 
     SELECT * 
     FROM res 
-1

con un CTE va a tener un problema con la recursividad si hay más de 100 artículos

Msg 530, nivel 16, estado 1, línea 20 La declaración finalizó. El recursión máxima 100 se ha agotado antes de completar la instrucción.

DECLARE @TExt NVARCHAR(MAX) 
SET @TExt = '100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203' 


DECLARE @Delimiter VARCHAR(1000)= ','; 
WITH numbers 
      AS (SELECT ROW_NUMBER() OVER (ORDER BY o.object_id, o2.object_id) Number 
       FROM  sys.objects o 
         CROSS JOIN sys.objects o2 
      ), 
     c AS (SELECT Number CHARBegin , 
         ROW_NUMBER() OVER (ORDER BY number) RN 
       FROM  numbers 
       WHERE SUBSTRING(@text, Number, LEN(@Delimiter)) = @Delimiter 
      ), 
     res 
      AS (SELECT CHARBegin , 
         CAST(LEFT(@text, charbegin) AS NVARCHAR(MAX)) Res , 
         RN 
       FROM  c 
       WHERE rn = 1 
       UNION ALL 
       SELECT c.CHARBegin , 
         CAST(SUBSTRING(@text, res.CHARBegin, 
             c.CHARBegin - res.CHARBegin) AS NVARCHAR(MAX)) , 
         c.RN 
       FROM  c 
         JOIN res ON c.RN = res.RN + 1 
      ) 
    SELECT * 
    FROM res 
0

Él es un ejemplo que puede utilizar:

-- Creating table: 
create table demo (dID int, dRec varchar(100)); 

-- Inserting records: 
insert into demo (dID, dRec) values (1, 'BCQP1 Sam'); 
insert into demo (dID, dRec) values (2, 'BCQP2 LD'); 

-- Selecting fields to retrive records: 
select * from demo; 

entonces quiero mostrar en una sola fila ambas filas combinadas y mostrar sólo los valores de la izquierda la supresión del nombre de la del lado derecho hasta el personaje del espacio.

/* 
    The STUFF() function puts a string in another string, from an initial position. 
    The LEFT() function returns the left part of a character string with the specified number of characters. 
    The CHARINDEX() string function returns the starting position of the specified expression in a character string. 
*/ 
SELECT 
DISTINCT 
    STUFF((SELECT ' ' + LEFT(dt1.dRec, charindex(' ', dt1.dRec) - 1) 
      FROM demo dt1 
      ORDER BY dRec 
      FOR XML PATH('')), 1, 1, '') [Convined values] 
FROM demo dt2 
-- 
GROUP BY dt2.dID, dt2.dRec 
ORDER BY 1 

Como se puede ver aquí cuando se ejecuta la función, la salida será:

BCQP1 BCQP2 

En la parte superior de la secuencia de comandos que se explica lo que cada función se utiliza para (cosas(), LEFT (), Funciones CHARINDEX()) También utilicé DISTINCT para eliminar valores duplicados.

NOTA: dt significa "mesa de demostración", he utilizado la misma mesa y usar dos DT1 alias y DT2, y dRec es sinónimo de "Registro de demostración"

Si desea obtener más información sobre la materia() Función aquí hay un enlace:

https://www.mssqltips.com/sqlservertip/2914/rolling-up-multiple-rows-into-a-single-row-and-column-for-sql-server-data/

Cuestiones relacionadas