2014-04-17 4 views
2

이미지이 테이블그룹화 교체

Table sentence 
-------------------------------------------------- 
| id | value   | 
-------------------------------------------------- 
| 1  | I own a $1 $3.| 
-------------------------------------------------- 

Table sentence_word_relations 
-------------------------------------------------- 
| sentence_id | word_id    
-------------------------------------------------- 
| 1    | 1     
-------------------------------------------------- 
| 1    | 3     
-------------------------------------------------- 

Table word 
-------------------------------------------------- 
| id   | value    
-------------------------------------------------- 
| 1    | red     
-------------------------------------------------- 
| 2    | blue     
-------------------------------------------------- 
| 3    | bike     
-------------------------------------------------- 
| 4    | house     
-------------------------------------------------- 

하나는 여러 문장을 만들 수있을 것입니다 : 나는 레드/블루 자전거/주택을 소유하고 있습니다. 문장에 포함 된 단어 변수에 따라 다릅니다. 문장이 갱신되고 달러 기호 다음에 값이 변경 되 자마자 관계 테이블이 그에 따라 업데이트됩니다.

- I own a red $3. 
- I own a $1 bike. 

가 하나 개의 행이 반환해야 할 수 있다면, 즉이 경우, 궁금가 : 나는 빨간 자전거를 소유하고 다음 쿼리 ...

SELECT 
    REPLACE(sentence.value, CONCAT('$', word.id), word.value) AS sentence 
FROM sentence 
JOIN sentence_word_relations 
ON sentence.id = sentence_word_relations.sentence_id 
JOIN word 
ON sentence_word_relations.word_id = word.id 

은 ... 자연스럽게 두 개의 행을 반환 .

+0

나는이 모든 것을 결합하기 위해 동적 SQL이 필요하다고 생각합니다. REPLACE ('$ 1', value1, REPLACE ('$ 2', value2, REPLACE ('$ 3', value3, ...))) ' – Barmar

+0

에 대한 대체는 호출 응용 프로그램 언어에서 수행하는 것이 더 쉽습니다. 예 : PHP에서는'$ n'과'value's의 배열을 생성 할 수 있고'str_replace()'를 한번에 호출 할 수 있습니다. – Barmar

+0

깔끔한 것은 아닙니다. 그래서 내가 물었다. – user2180613

답변

1

만 다음 당신이 사용할 수있는 2 개 개의 단어가있는 경우 : -

SELECT REPLACE(REPLACE(sentence.value, CONCAT('$', word1.id), word1.value), CONCAT('$', word2.id), word2.value) AS sentence 
FROM sentence 
JOIN sentence_word_relations AS swr1 ON sentence.id = swr1.sentence_id 
JOIN word AS word1 ON swr1.word_id = word1.id 
JOIN sentence_word_relations AS swr2 ON sentence.id = swr2.sentence_id 
JOIN word AS word2 ON swr2.word_id = word2.id 

하지만이 매우 제한됩니다. 최대 교체 횟수가 매우 적 으면이 방법을 사용할 수 있습니다 (대체 값이 최대 값보다 적 으면 테이블에 LEFT OUTER JOIN을 사용하여 대처할 수 있습니다)

대체품을 그룹화 한 다음 -

SELECT sentence, GROUP_CONCAT(CONCAT_WS('~', word1.id, word1.value)) 
FROM sentence 
JOIN sentence_word_relations AS swr ON sentence.id = swr.sentence_id 
JOIN word AS word ON swr.word_id = word.id 
GROUP BY sentence 

이 작업을 수행 할 수도 있지만 대체 할 수있는 MySQL 사용자 정의 함수를 호출 할 수 있습니다. 이것은 아마도 가장 우아한 해결책 일 것입니다.

편집 - 그냥 장난,하지만 당신은 PHP를 사용한다면 아무도 당신이 시도 할 수 편집 할 없을 것입니다 몇 가지 끔찍한 SQL 참을 수 : -로 대체 값을 포맷하는

SELECT sentence, 
    CONCAT('a:', COUNT(word.id), ':{', 
    GROUP_CONCAT(
    CONCAT(
    'i:', 
    word.id, 
    ';a:2:{', 
    CONCAT('s:', LENGTH('word.id'), ':\"', 'word.id', '\";s:', LENGTH(word.id), ':\"', word.id, '\";'), 
    CONCAT('s:', LENGTH('word.value'), ':\"', 'word.value', '\";s:', LENGTH(word.value), ':\"', word.value, '\";'), 
    '}' 
    ) 
    SEPARATOR ''), 
    '}' 
    ) AS replacement_details 
FROM sentence 
JOIN sentence_word_relations AS swr ON sentence.id = swr.sentence_id 
JOIN word AS word ON swr.word_id = word.id 
GROUP BY sentence 

PHP 직렬 배열. 테이블에서 행을 읽고 두 번째 필드를 직렬화 해제 한 다음 교체 작업을 수행하는 요소를 반복 할 수 있습니다. 가능한 다양한 언어로 처리 할 수있는 JSON 인코딩 된 배열을 구축하는 것과 비슷한 작업을 수행 할 수 있습니다.

이것은 예외적 인 상황을 제외하고는 진지한 제안 이라기보다는 오락을 위해 더 많은 일을했다.

대체 단어에 임의의 문자가 포함될 수있는 경우 대체 값이 다른 값의 마커가 될 가능성이 있습니다 (예 : 단어 1이 실제로 '$ 3'이고 문장에서 $ 1이 $ 3로 변경하고 다음 번 교체가 완료되면 자전거로 변경되어 의 문자열을 제공합니다.)

+0

대체 횟수는 완전히 알려져 있지 않습니다. 문장은 10 개뿐 아니라 대체 할 필요도 없다. 두 번째 해결 방법에 대해서는 단어 사이에 임의의 문자가 포함될 수 있으므로 값 사이에 구분 기호를 사용할 수 없습니다. – user2180613

+0

당신이 사용하는 구분 기호는 이유 안에있는 어떤 것도 될 수 있습니다. 여러 문자를 사용하고 결코 사용해서는 안되는 이상한 점. 어떤 언어를 이것을 부름니까? – Kickstart

+0

내가 생각할 수있는 가장 특이한 구획 문자를 사용한다고하더라도 충돌의 가능성은 여전히 ​​있습니다 (나는 편집증이라고 생각하지만 그것은 항상 피하려고하는 것입니다). 내가 사용하는 언어는 PHP입니다. 나는 각 문장의 id로 결과를 그룹화 한 다음 문장마다 각 변수 세트를 대체하기로 결정했다. – user2180613