Pokud opravdu nemůžete upravit strukturu tabulky, pravděpodobně nejlepší, co můžete udělat, je jeden ze starých hacků seznamů:
-
Použijte
JOIN
s FIND_IN_SET(hodnota, čárkaSeparatedString)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 ;
-
Použijte
LIKE
k detekci přítomnosti konkrétní hodnoty serviceID v seznamu uzlů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 ;
Jak jste však již poznamenali, sloupec by skutečně měl být normalizován. Zatímco výše uvedené metody by měly fungovat pro malé soubory dat, trpí obvyklými problémy práce se „seznamy“. Ani jedna metoda není příliš přátelská k indexům a v důsledku toho se nebude dobře škálovat. Oba také provádějí porovnávání řetězců. Takže sebemenší rozdíl může způsobit selhání párování. Například 1,4
by odpovídalo dvěma serviceID, zatímco 1,(space)4
nebo 1,4.0
odpovídá pouze jednomu.
Aktualizace na základě komentářů:
Při druhém přečtení si nejsem jistý, že výše uvedené odpovědi přesně odpovídají na otázku, na kterou se ptáte, ale mělo by to poskytnout dobrý základ pro práci s ...
Pokud již nechcete seznam CSV, stačí použít jeden z výše uvedených dotazů a vypsat jednotlivé sloupce dotazů jako obvykle. Výsledkem bude jeden název služby na řádek, tj.:
server1 | Control Name One | Service Name 200
server1 | Control Name One | Service Name 50
..
V opačném případě, pokud potřebujete zachovat hodnoty oddělené čárkami, jednou z možností je použít <cfoutput group="..">
na výsledky dotazu. Vzhledem k tomu, že výsledky jsou nejprve seřazeny podle "hostitele", něco jako kód níže. Poznámka: Aby "skupina" fungovala správně, musí být výsledky seřazeny podle Host
a musíte použít více cfoutput
značky, jak je uvedeno níže.
<cfoutput query="..." group="Host">
#Host# |
#ControlName# |
<cfoutput>
#ServiceName#,
</cfoutput>
<br>
</cfoutput>
Výsledek by měl vypadat takto:
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,
Aktualizace 2:
Zapomněl jsem, že existuje jednodušší alternativa k cfoutput group
v 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>