Mysql
 sql >> база данни >  >> RDS >> Mysql

SQL заявка за множество таблици, с множество съединения и поле с колони със списък, разделен със запетая

Ако наистина не можете да промените структурата на таблицата, вероятно най-доброто, което можете да направите, е един от старите хакове за списък:

  • Използвайте 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 ;

SQLPiddle

Въпреки това, както вече отбелязахте, тази колона наистина трябва да бъде нормализирана. Докато методите по-горе трябва да работят за малки набори от данни, те страдат от обичайните проблеми при работа със „списъци“. Нито един метод не е много удобен за индекси и в резултат на това няма да се мащабира добре. Освен това и двете извършват сравнения на низове. Така че най-малката разлика може да доведе до неуспех на съвпадението. Например 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>



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как работи функцията CHARACTER_LENGTH() в MySQL

  2. MYSQL контрол на достъпа

  3. Използване на Workbench за свързване към отдалечен MySQL сървър през SSH тунел

  4. MySQL Workbench не може да се свърже със сървър на база данни

  5. Как се използват алгоритмите за класиране на Reddit и Hacker News?