Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySql-Abfrage, um alle Kombinationen von zwei Spalten mit NULL zu erhalten, wenn es keinen übereinstimmenden Datensatz gibt

Ihr erster äußerer Join , wie erwartet, erzeugt:

| REASON |  MONTH |
-------------------
|      A |    May |
|      A |    May |
|      A |   July |
|      A |   June |
|      B |    May |
|      B |   June |
|      D | (null) |

Da Outer Joins jedoch Ergebnisse liefern, wenn die Join-Bedingung mindestens einmal erfüllt ist (und nur NULL einführen Aufzeichnungen, wenn die Bedingung nie ist zufrieden), Ihr zweiter äußerer Join dann nicht Produziere einen Datensatz für (B, July); es löscht auch Reason = 'D' vollständig, weil die Join-Bedingung nicht erfüllt ist (und alle drei Monate an anderer Stelle erfüllt wurden):

| REASON | MONTH |
------------------
|      A |   May |
|      A |   May |
|      B |   May |
|      A |  June |
|      B |  June |
|      A |  July |

Während Sie könnten den Verlust von Reason = 'D' beheben durch Hinzufügen OR a.Month IS NULL Ihrer Join-Bedingung entsprechen, werden Sie (B, July) immer noch nicht produzieren . Stattdessen, weil Sie jedes Paar (Reason, Month) erhalten möchten , müssen Sie CROSS JOIN Ihre materialisierten Reasons Tabelle mit Ihren materialisierten Months Tabelle:

SELECT Reason, Month
FROM   
  (
    SELECT 'A' AS Reason
    UNION ALL SELECT 'B'
    UNION ALL SELECT 'D'
  ) Reasons CROSS JOIN (
    SELECT 'May' AS Month
    UNION ALL SELECT 'June'
    UNION ALL SELECT 'July'
  ) Months
| REASON | MONTH |
------------------
|      A |   May |
|      B |   May |
|      D |   May |
|      A |  June |
|      B |  June |
|      D |  June |
|      A |  July |
|      B |  July |
|      D |  July |

Sehen Sie es auf sqlfiddle .

Sie müssen dann nur noch das Ergebnis mit Ihren zugrunde liegenden Daten verbinden:

SELECT Reason, Month, SUM(Down_time) downtime
FROM   
  (
    SELECT 'A' AS Reason
    UNION ALL SELECT 'B'
    UNION ALL SELECT 'D'
  ) Reasons CROSS JOIN (
    SELECT 'May' AS Month
    UNION ALL SELECT 'June'
    UNION ALL SELECT 'July'
  ) Months
  LEFT JOIN tabledown USING (Reason, Month)
GROUP BY Reason, Month
| REASON | MONTH | DOWNTIME |
-----------------------------
|      A |  July |        3 |
|      A |  June |        8 |
|      A |   May |        7 |
|      B |  July |   (null) |
|      B |  June |        6 |
|      B |   May |        5 |
|      D |  July |   (null) |
|      D |  June |   (null) |
|      D |   May |   (null) |

Sehen Sie es auf sqlfiddle .