2012-05-29 4 views
3

쿼리 할 대상이 아닌 XML 데이터이기 때문에 여러 값을 포함하는 비정규 필드가 있습니다. , 지금까지. MySQL이이 xml 열을 여러 행으로 나눌 수 있습니까?MySQL은 ExtractValue (XML, 'Value/Values')를 사용하여 여러 값을 가져옵니다 (하나의 열을 행으로 분할 함)

표이 MSSQL/TSQL 솔루션처럼

NameA | 1 
NameA | 2 
NameA | 3 
NameB | 1 

을 원하는

NameA | <Xml><Values<Value>1</Value><Value>2</Value><Value>3</Value></Values></Xml> 
NameB | <Xml><Values<Value>1</Value><Value>2</Value></Values></Xml> 
NameC | <Xml><Values<Value>1</Value><Value>2</Value><Value>3</Value><Value>4</Value></Values></Xml> 

SELECT 
    I.Name, 
    Value.value('.','VARCHAR(30)') AS Value 
FROM 
    Item AS I 
CROSS APPLY 
    Xml.nodes('/Xml/Values/Value') AS T(Value) 
WHERE 
    I.TypeID = 'A' 

그러나

MySQL의에서 난 단지 얻을 수

NameA | 123 
NameB | 12 
NameC | 1234 
MySQL의에서 XML을 분할하는 어떤 우아한 방법이
SELECT 
    I.`Name`, 
    ExtractValue(Xml,'/Xml/Values/Value') AS ListOfValues 
FROM 
    Item AS I 
WHERE 
    I.TypeID = 'A' 
; 

이 있습니까?

답변

7

아니요. 다른 MySQL 분할 열 문제와 마찬가지로이 문제를 해결해야합니다.

즉, 특별히

DROP PROCEDURE IF EXISTS GetNameValues $$ 
CREATE PROCEDURE GetNameValues() 
BEGIN 
    DECLARE i INTEGER; 

    DROP TEMPORARY TABLE IF EXISTS TempList; 
    CREATE TEMPORARY TABLE TempList(
     `Name` VARCHAR(256) COLLATE utf8_unicode_ci NOT NULL, 
     `ValueList` VARCHAR(20000) COLLATE utf8_unicode_ci NOT NULL 
    ); 
    DROP TEMPORARY TABLE IF EXISTS Result; 
    CREATE TEMPORARY TABLE Result(
     `Name` VARCHAR(256) COLLATE utf8_unicode_ci NOT NULL, 
     `Value` VARCHAR(128) COLLATE utf8_unicode_ci NOT NULL 
    ); 

    INSERT INTO 
     TempList 
    SELECT 
     I.`Name`, 
     ExtractValue(Xml,'/Xml/Values/Value') AS ValueList 
    FROM 
     Item AS I 
    WHERE 
     I.TypeID = 'A' 
    ; 

    SET i = 1; 
    REPEAT 
     INSERT INTO 
      Result 
     SELECT 
      `Name`, 
      CAST(STRSPLIT(ValueList, ' ', i) AS CHAR(128)) AS Value 
     FROM 
      TempList 
     WHERE 
      CAST(STRSPLIT(ValueList, ' ', i) AS CHAR(128)) IS NOT NULL 
     ; 

     SET i = i + 1; 
     UNTIL ROW_COUNT() = 0 
    END REPEAT; 

    SELECT * FROM Result ORDER BY `Name`; 
END $$ 

DELIMITER ; 

CALL GetNameValues(); 

희망 같은 값을 통해 this answer

DROP FUNCTION IF EXISTS STRSPLIT; 
DELIMITER $$ 
CREATE FUNCTION STRSPLIT($Str VARCHAR(20000), $delim VARCHAR(12), $pos INTEGER) 
    RETURNS VARCHAR(20000) 
BEGIN 
    DECLARE output VARCHAR(20000); 

    SET output = REPLACE(SUBSTRING(SUBSTRING_INDEX($Str, $delim, $pos) 
       , LENGTH(SUBSTRING_INDEX($Str, $delim, $pos - 1)) + 1) 
       , $delim 
       , ''); 

    IF output = '' 
     THEN SET output = null; 
    END IF; 

    RETURN output; 
END $$ 

당신은 반복 할 수에 따라이 사람 일일에게 도움이됩니다.

관련 문제