Om du verkligen inte kan ändra tabellstrukturen är förmodligen det bästa du kan göra ett av de gamla listhackarna:
-
Använd en
JOIN
med FIND_IN_SET(value, 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 ;
-
Använd
LIKE
för att upptäcka närvaron av ett specifikt serviceID-värde i nodlistanSELECT 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 ;
Men som du redan har noterat borde kolumnen verkligen normaliseras. Även om metoderna ovan borde fungera för små datamängder, lider de av de vanliga problemen med att arbeta med "listor". Ingen av metoderna är särskilt indexvänlig och kommer som ett resultat inte att skala bra. Båda utför också strängjämförelser. Så den minsta skillnaden kan göra att matchningen misslyckas. Till exempel 1,4
skulle matcha två serviceID:n, medan 1,(space)4
eller 1,4.0
skulle bara matcha en.
Uppdatering baserat på kommentarer:
Vid andra läsningen är jag inte säker på att ovanstående svarar på den exakta frågan du ställer, men det borde ge en bra grund att arbeta med ...
Om du inte längre vill ha en CSV-lista använder du bara en av frågorna ovan och matar ut de enskilda frågekolumnerna som vanligt. Resultatet blir ett tjänstnamn per rad, dvs:
server1 | Control Name One | Service Name 200
server1 | Control Name One | Service Name 50
..
Annars, om du behöver bevara de kommaseparerade värdena, är en möjlighet att använda en <cfoutput group="..">
på frågeresultaten. Eftersom resultaten är sorterade efter "värd" först, ungefär som koden nedan. Obs! För att "grupp" ska fungera korrekt måste resultaten sorteras efter Host
och du måste använda flera cfoutput
taggar som visas nedan.
<cfoutput query="..." group="Host">
#Host# |
#ControlName# |
<cfoutput>
#ServiceName#,
</cfoutput>
<br>
</cfoutput>
Resultatet ska se ut så här:
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,
Uppdatering 2:
Jag glömde att det finns ett enklare alternativ till cfoutput group
i 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>