Ако наистина не можете да промените структурата на таблицата, вероятно най-доброто, което можете да направите, е един от старите хакове за списък:
-
Използвайте
JOIN
с FIND_IN_SET(стойност, commaSeparatedString)SELECT n.Host, c.Name AS ControlName, s.Name AS ServiceName FROM node n LEFT JOIN control c ON c.controlID = n.controlID LEFT JOIN service s ON FIND_IN_SET(s.serviceID, n.serviceId) ORDER BY n.host, s.Name ;
-
Използвайте
LIKE
за откриване на наличието на специфична стойност на serviceID в списъка с възлиSELECT n.Host, c.Name AS ControlName, s.Name AS ServiceName FROM node n LEFT JOIN control c ON c.controlID = n.controlID LEFT JOIN service s ON CONCAT(',', n.serviceID,',') LIKE CONCAT('%,', s.serviceID,',%') ORDER BY n.host, s.Name ;
Въпреки това, както вече отбелязахте, тази колона наистина трябва да бъде нормализирана. Докато методите по-горе трябва да работят за малки набори от данни, те страдат от обичайните проблеми при работа със „списъци“. Нито един метод не е много удобен за индекси и в резултат на това няма да се мащабира добре. Освен това и двете извършват сравнения на низове. Така че най-малката разлика може да доведе до неуспех на съвпадението. Например 1,4
ще съответства на два serviceID, докато 1,(space)4
или 1,4.0
ще съвпада само с едно.
Актуализация въз основа на коментари:
При второ четене не съм сигурен, че горното отговаря на точния въпрос, който задавате, но трябва да осигури добра основа за работа с ...
Ако вече не искате CSV списък, просто използвайте една от заявките по-горе и изведете отделните колони на заявката както обикновено. Резултатът ще бъде едно име на услуга на ред, т.е.:
server1 | Control Name One | Service Name 200
server1 | Control Name One | Service Name 50
..
В противен случай, ако трябва да запазите стойностите, разделени със запетая, една от възможностите е да използвате <cfoutput group="..">
върху резултатите от заявката. Тъй като резултатите са подредени първо от "Хост", нещо като кода по-долу. Забележка: За да работи "групата" правилно, резултатите трябва да бъдат подредени от Host
и трябва да използвате множество cfoutput
тагове, както е показано по-долу.
<cfoutput query="..." group="Host">
#Host# |
#ControlName# |
<cfoutput>
#ServiceName#,
</cfoutput>
<br>
</cfoutput>
Резултатът трябва да изглежда така:
server1 | Control Name One | Service Name 200, Service Name 50, Service Name Four, Service Name One, Service Name Three, Service Name Two,
server2 | Control Name Two | Service Name 200, Service Name Four, Service Name Three, Service Name Two,
server3 | Control Name Two | Service Name 200, Service Name 50, Service Name Four, Service Name One, Service Name Three, Service Name Two,
server4 | Control Name Three | Service Name 200, Service Name 50, Service Name One, Service Name Two,
server5 | Control Name Three | Service Name Four, Service Name One,
Актуализация 2:
Забравих, че има по-проста алтернатива на cfoutput group
в MySQL:GROUP_CONCAT
<cfquery name="qry" datasource="MySQL5">
SELECT n.Host, c.Name AS ControlName, GROUP_CONCAT(s.Name) AS ServiceNameList
FROM node n
LEFT JOIN control c ON c.controlID = n.controlID
LEFT JOIN service s ON FIND_IN_SET(s.serviceID, n.serviceId)
GROUP BY n.Host, c.Name
ORDER BY n.host
</cfquery>