- Community Pick
- Experts Exchange Approved
Are you ready for another of my SQL tidbits? Hopefully so, as in this adventure, I will be covering a topic that comes up a lot which is parsing a comma (or otherwise) delimited string into rows (or columns) of data.
The methodology to be used takes advantage of some of MySQL's Extensible Markup Language (XML) functionality and so this Article will apply to MySQL 5.1.5 or higher. Consequently, if you are a MySQL developer using the newer version of MySQL or even just an avid reader, please read on and enjoy!
Sections
- Background
- Thinking XML
- XML Parsing Trick in Action
- 1
Background
Recently, EE Member transitnetwork, asked a Question, How do I make delimited fields come out in a list with totals, which my technique fit perfectly (at least as one method of getting the job done).
The Request
I want to make the results look like this:
- ""]««setup»»
To follow along in the article, here are scripts to get started with.
(table structure -- create statement)
(sample data -- insert statement)
With a quick selection of the above data, you can verify that your input looks like Figure 1.1.
In addition, we will take advantage of a having a numbers utility table in our database, so run this:
(explanation: A MySQL Tidbit: Quick Numbers Table Generation)
- 2
Thinking XML
My mind has been on XML because of what I am researching at work coupled with other Article code I have been playing with of late. Others and I have used this same logic in T-SQL here at EE before; therefore, for me it isn't too far a stretch to consider taking delimited text and converting it to well-formed XML, so good bad or indifferent that is what this technique is all about!
To accomplish this transformation, we simply replace comma (or other delimiter) with element tags we want, ensuring to wrap (concatenate) the result with a start and end tag.
(resulting in something like this for example)
In the code of the Question, I put a root element (e.g., <cuisines>) around the above because it didn't feel right to not make a valid XML document, but note that the XML fragment without root node would work just as fine. I understand that as programmers, we love anything that will save keystrokes. Therefore, on that note, keep in mind that this XML is just a means to an end, so it doesn't matter how it looks. I spelled out elements, originally, to make it clearer what I was doing, but we can make it real short hand (i.e., more generic and reusable like r = row; c = column):
(and now the big unveil) TADA!
(results)
Putting our query into a derived table for ease of referencing the field xml, the solution above makes use of ExtractValue(), one of the two MySQL XML functions. As a refresher, ExtractValue() takes the following form:
So, the xml column we crafted for our trick is the first parameter and the second is standard XPath, which requires you specify an index (e.g., 1-5) when there are multiple nodes that can match a specific path. Note: The requirement for the index (or more precisely having to code a finite number of columns) is a limitation or at a consideration. In the example, I simply chose 5 cuisines to display. If we had restaurants with more, only the first 5 would show and, as you can see by the highlighted cell above, those with less simply show with blank spots ('').
But having to type out (really, cut and paste) the formula for each column isn't too bad, but look at how the limitation is exaggerated when you want to get rows instead.
It works, though, so there's nothing wrong with using it if it comes in handy within a given scenario.
But there is a more efficient way, right ?
- 3
XML Parsing Trick in Action
Now that we have built a piece of XML string, we can apply our MySQL in-line XML parsing trick to it. Therefore, putting the creation of XML from the CSV string together with our numbers table technique for parsing XML in a single query could result in a solution to the original problem that looks like this:
(results)
- ""]««bonus»»
With MySQL's Group_Concat, we can get list of restaurants in a delimited list by each count.
(http://dev.mysql.com/doc/refman/5.0 /en/group- by- functio ns.html#fu nction_gro up-concat)
(results)
'tis complete!
Conclusion
Simple enough to follow? By this point, I hope that you are comfortable with using Replace() and Concat() to transform a delimited string value into XML; subsequently, I hope that you are now knowledgeable on the ExtractValue() technique for parsing this same XML into columns or rows of data. Have you been following along? You can test for yourself and you should see the power and results work magically in front of your eyes, proving this is a useful tip and not just Article trickery by using the same image *smile* for both code block results (lazy author *laughing*).
As usual, I would love to hear what you think and any questions regarding this technique in comments. If you have a specific application of this that you are having difficulty with, just remember the Q&A topic area for MySQL is the best place to go.
Thank you, all, for reading…until next time!
Best regards and happy coding,
Kevin C. Cross, Sr. (mwvisa1)
References
Related Articles
http://www.experts-exchang
http://www.experts-exchang
http://www.experts-exchang
http://www.experts-exchang
Related MySQL Documentation
http://dev.mysql.com/doc/r
http://dev.mysql.com/doc/r
http://dev.mysql.com/doc/r
http://dev.mysql.com/doc/r
Related Q&A
http://www.experts-exchang
=-=-=-=-=-=-=-=-=-=-=-=-=-
If you found this article helpful, please click the Yes button after the question just below. This will give me (the author) a few points and might encourage me to write more articles.
If you didn't or otherwise feel the need to vote No, please first leave a comment to give me a chance to answer and perhaps to improve this article.
Thank you!
=-=-=-=-=-=-=-=-=-=-=-=-=-
by: aikimark on 2010-08-26 at 05:11:30ID: 18760
It's good to see you're getting some mileage out of the XML parsing trick. This is an excellent sequel. As usual, I've learned new things like Group_Concat()
Thank you for the http://e-e.com/A_1536.html