sql >> Database >  >> RDS >> Mysql

SQL-query meerdere tabellen, met meerdere joins en kolomveld met door komma's gescheiden lijst

Als u de tabelstructuur echt niet kunt wijzigen, kunt u waarschijnlijk het beste een van de oude lijsthacks gebruiken:

  • Gebruik een JOIN met 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 ;

  • Gebruik LIKE om de aanwezigheid van een specifieke serviceID-waarde in de knooppuntlijst te detecteren

    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 ;

SQLFiddle

Zoals u echter al opmerkte, zou die kolom echt moeten worden genormaliseerd. Hoewel de bovenstaande methoden zouden moeten werken voor kleine datasets, hebben ze last van de gebruikelijke problemen bij het werken met "lijsten". Geen van beide methoden is erg indexvriendelijk en zal daarom niet goed schalen. Beide voeren ook tekenreeksvergelijkingen uit. Dus het kleinste verschil kan ervoor zorgen dat de matching mislukt. Bijvoorbeeld 1,4 zou overeenkomen met twee serviceID's, terwijl 1,(space)4 of 1,4.0 zou er maar één matchen.

Update op basis van opmerkingen:

Bij de tweede lezing weet ik niet zeker of het bovenstaande de precieze vraag beantwoordt die u stelt, maar het zou een goede basis moeten bieden om mee te werken ...

Als u niet langer een CSV-lijst wilt, gebruikt u gewoon een van de bovenstaande query's en voert u de afzonderlijke querykolommen uit zoals gewoonlijk. Het resultaat is één servicenaam per rij, dat wil zeggen:

   server1 | Control Name One | Service Name 200
   server1 | Control Name One | Service Name 50
   ..

Als u de door komma's gescheiden waarden wilt behouden, kunt u een <cfoutput group=".."> gebruiken. op de vraagresultaten. Aangezien de resultaten eerst op "Host" worden gerangschikt, zoiets als de onderstaande code. NB: Om "groep" goed te laten werken, moeten de resultaten worden besteld door Host en je moet meerdere cfoutput . gebruiken tags zoals hieronder weergegeven.

 <cfoutput query="..." group="Host"> 
    #Host# |
    #ControlName# |
    <cfoutput>
      #ServiceName#,
    </cfoutput>
    <br>
 </cfoutput>

Het resultaat zou er als volgt uit moeten zien:

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, 


Update 2:

Ik was vergeten dat er een eenvoudiger alternatief is voor cfoutput group in 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>



  1. Een datatabel invullen in C# met MySQL

  2. Waarom de init_command set engine=INNODB van django DATABASE_OPTIONS verwijderen na het maken van een tabel?

  3. Hoe gegevens terug te krijgen van Mysql voor dagen zonder statistieken?

  4. Aan de slag met Shareplex op Windows op AWS, deel 1