如果您确实无法修改表结构,则可能最好的方法是使用旧列表技巧之一:
- 使用
JOIN
与FIND_IN_SET(值,commaSeparatedString)
SELECt n.Host, c.Name AS ControlName, s.Name AS ServiceName FROM node n LEFTJOIN control c ON c.controlID = n.controlID LEFT JOIN service s ONFIND_IN_SET(s.serviceID, n.serviceId) ORDER BY n.host, s.Name ;
- 使用
LIKE
检测节点列表中的特定服务ID值的存在
SELECt n.Host, c.Name AS ControlName, s.Name AS ServiceName FROM node n LEFTJOIN 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;SQLFiddle
但是,正如您已经指出的,该列确实应该被规范化。尽管上面的方法应该适用于小型数据集,但是它们却遇到了使用“列表”的常见问题。两种方法都不十分适合索引,因此无法很好地扩展。同样,它们都执行字符串比较。因此,最微小的差异可能会导致匹配失败。例如,
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="..">查询结果使用a
。由于结果首先由“主机”排序,因此类似于下面的代码。 注意:
要使“组”正常工作,必须按以下顺序对结果进行排序,
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:
我忘记了
cfoutputgroup在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>



