Domanda

Image these tables

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                 
--------------------------------------------------

One should be able to create multiple sentences: I own a red/blue bike/house. That depends on the word variables the sentence contains. As soon as a sentence is updated and the value after the dollar sign changes, the relations table gets updated accordingly. The following query...

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

...naturally returns two rows:

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

I wonder if it is possible to have one row returned, in this case namely: I own a red bike.

È stato utile?

Soluzione

If you only have 2 words then you can use this:-

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

but that is very limiting. If the max number of replacements is fairly small this would probably be workable (you could use LEFT OUTER JOINs to the tables to cope when there are less replacements than the maximum)

You could group up the replacements and then deal it with in your chosen programming language:-

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

You could possibly also do this, but calling a MySQL custom function to do the replacement. This would probably be the most elegant solution.

EDIT - Just playing around, but if you were using php and could put up with some hideous SQL that nobody would want to edit you could try this:-

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

That is formatting the replacement values into a php serialized array. You could just read the row from the table, unserialize the 2nd field and loop through the elements performing the replacement. You could possible do something similar to build up a JSON encoded array that could be processed in a wider variety of languages.

That said this was more done for amusement rather than a serious suggestion except under exceptional circumstances.

By the way if your replacement words can contain any character then you also have a potential issue with a replacement being the marker for a different value (ie, say word 1 was actually '$3', then $1 in the sentence would be changed to $3, and then when the next replacement is done that will be changed to bike, giving a string of 'I own a bike bike.' )

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top