2017-11-01 7 views
0

Guten Tag, Ich versuche, eine SQL-Anweisung zu erstellen, um Statusdaten für die letzten 14 Tage für alle 4 Benutzer zurückgeben. Ich habe eine Kalendertabelle erstellt, um einen LEFT JOIN durchzuführen. die backupdata Tabelle angegeben:Mysql Left Join für Tage, die keine Daten haben

+----------+-------------+------------+-----------+------------------- 
--+ 
| customer | Category | user  | status | Date     
| 
+----------+-------------+------------+-----------+---------------------+ 
| acme  | Workstation | Judi  | [Success] | 2017-10-18 10:29:08 | 
| acme  | Server  | Quickbooks | [Success] | 2017-10-18 11:25:33 | 
| acme  | Server  | Quickbooks | [Success] | 2017-10-18 11:33:56 | 
| acme  | Workstation | Reception | [Success] | 2017-10-18 12:14:49 | 
| acme  | Workstation | Megan  | [Success] | 2017-10-18 16:10:24 | 
| acme  | Workstation | Judi  | [Success] | 2017-10-18 16:11:03 | 
| acme  | Workstation | Reception | [Success] | 2017-10-19 08:04:15 | 
| acme  | Server  | Quickbooks | [Success] | 2017-10-19 11:35:47 | 
| acme  | Workstation | Judi  | [Success] | 2017-10-19 16:10:13 | 
| acme  | Workstation | Reception | [Success] | 2017-10-20 08:35:26 | 
| acme  | Server  | Quickbooks | [Success] | 2017-10-20 13:28:08 | 
| acme  | Workstation | Judi  | [Success] | 2017-10-20 16:09:00 | 
| acme  | Server  | Quickbooks | [Success] | 2017-10-21 11:33:28 | 
| acme  | Workstation | Judi  | [Success] | 2017-10-21 16:11:01 | 
| acme  | Server  | Quickbooks | [Success] | 2017-10-22 11:33:16 | 
+----------+-------------+------------+-----------+---------------------+ 

ich die Daten so präsentieren wollen:

+------------+------------+-----------+ 
| dt   | User  | Status | 
+------------+------------+-----------+ 
| 2017-10-18 | Judi  | [Success] | 
| 2017-10-18 | Megan  | [Success] | 
| 2017-10-18 | Quickbooks | [Success] | 
| 2017-10-18 | Reception | [Success] | 
| 2017-10-19 | Judi  | [Success] | 
| 2017-10-19 | Quickbooks | [Success] | 
| 2017-10-19 | Reception | [Success] | 
| 2017-10-19 | Megan  | No Data | 
| 2017-10-20 | Judi  | [Success] | 
| 2017-10-20 | Quickbooks | [Success] | 
| 2017-10-20 | Reception | [Success] | 
| 2017-10-20 | Megan  | No Data | 
| 2017-10-21 | Judi  | [Success] | 
| 2017-10-21 | Quickbooks | [Success] | 
| 2017-10-21 | Megan  | No Data | 
| 2017-10-21 | Reception | [Success] | 
| 2017-10-22 | Judi  | [Success] | 
| 2017-10-22 | Quickbooks | [Success] | 
| 2017-10-22 | Megan  | No Data | 
| 2017-10-22 | Reception | No Data | 
| 2017-10-23 | Judi  | [Success] | 
| 2017-10-23 | Reception | [Success] | 
| 2017-10-23 | Quickbooks | No Data | 
| 2017-10-23 | Megan  | No Data | 

Tage ohne Daten müssen als "NO DATA" für einen Benutzer angezeigt werden. Meine aktuelle Abfrage ist die Beseitigung von Nullwerten in denen bestimmte Benutzer keine Statusdaten für einen bestimmten Tag haben als die anderen Benutzer Daten für diesen Tag haben können:

SELECT calendar_table.dt,BackupDetail.User, BackupDetail.Status 
FROM calendar_table 
LEFT JOIN BackupDetail ON (calendar_table.dt = 
DATE(BackupDetail.Date)) 
where calendar_table.dt BETWEEN date_add(curdate(), interval -14 day) 
AND curdate() 
GROUP BY calendar_table.dt,BackupDetail.User 

Ergebnisse in:

+------------+------------+-----------+ 
| dt   | User  | Status | 
+------------+------------+-----------+ 
| 2017-10-18 | Judi  | [Success] | 
| 2017-10-18 | Megan  | [Success] | 
| 2017-10-18 | Quickbooks | [Success] | 
| 2017-10-18 | Reception | [Success] | 
| 2017-10-19 | Judi  | [Success] | 
| 2017-10-19 | Quickbooks | [Success] | 
| 2017-10-19 | Reception | [Success] | 
| 2017-10-20 | Judi  | [Success] | 
| 2017-10-20 | Quickbooks | [Success] | 
| 2017-10-20 | Reception | [Success] | 
| 2017-10-21 | Judi  | [Success] | 
| 2017-10-21 | Quickbooks | [Success] | 
| 2017-10-22 | Judi  | [Success] | 
| 2017-10-22 | Quickbooks | [Success] | 
| 2017-10-23 | Judi  | [Success] | 
| 2017-10-23 | Reception | [Success] | 
| 2017-10-24 | Judi  | [Success] | 
| 2017-10-24 | Megan  | [Failed] | 
| 2017-10-24 | Quickbooks | [Success] | 
| 2017-10-25 | Judi  | [Success] | 
| 2017-10-25 | Megan  | [Success] | 
| 2017-10-25 | Quickbooks | [Success] | 
| 2017-10-25 | Reception | [Success] | 
| 2017-10-26 | Judi  | [Success] | 
| 2017-10-26 | Megan  | [Success] | 
| 2017-10-26 | Quickbooks | [Success] | 
| 2017-10-26 | Reception | [Success] | 
| 2017-10-27 | Judi  | [Success] | 
| 2017-10-27 | Quickbooks | [Success] | 
| 2017-10-27 | Reception | [Success] | 
| 2017-10-28 | Judi  | [Success] | 
| 2017-10-28 | Quickbooks | [Success] | 
| 2017-10-29 | Judi  | [Success] | 
| 2017-10-29 | Quickbooks | [Success] | 
| 2017-10-30 | Judi  | [Success] | 
| 2017-10-30 | Megan  | [Success] | 
| 2017-10-30 | Quickbooks | [Success] | 
| 2017-10-30 | Reception | [Success] | 
| 2017-10-31 | Megan  | [Success] | 
| 2017-10-31 | Reception | [Success] | 
| 2017-11-01 | NULL  | NULL  | 
+------------+------------+-----------+ 

Wenn ich ändern die Abfrage einen bestimmten Benutzer in der zur Abfrage JOIN:

SELECT calendar_table.dt,BackupDetail.User, BackupDetail.Status 
FROM calendar_table 
LEFT JOIN BackupDetail ON (calendar_table.dt = 
DATE(BackupDetail.Date) and BackupDetail.User = 'Quickbooks') 

where calendar_table.dt BETWEEN date_add(curdate(), interval -14 day) 
AND curdate() 

GROUP BY calendar_table.dt,BackupDetail.User 

ich näher an das gewünschte Ergebnis:

+------------+------------+-----------+ 
| dt   | User  | Status | 
+------------+------------+-----------+ 
| 2017-10-18 | Quickbooks | [Success] | 
| 2017-10-19 | Quickbooks | [Success] | 
| 2017-10-20 | Quickbooks | [Success] | 
| 2017-10-21 | Quickbooks | [Success] | 
| 2017-10-22 | Quickbooks | [Success] | 
| 2017-10-23 | NULL  | NULL  | 
| 2017-10-24 | Quickbooks | [Success] | 
| 2017-10-25 | Quickbooks | [Success] | 
| 2017-10-26 | Quickbooks | [Success] | 
| 2017-10-27 | Quickbooks | [Success] | 
| 2017-10-28 | Quickbooks | [Success] | 
| 2017-10-29 | Quickbooks | [Success] | 
| 2017-10-30 | Quickbooks | [Success] | 
| 2017-10-31 | NULL  | NULL  | 
| 2017-11-01 | NULL  | NULL  | 
+------------+------------+-----------+ 

Wenn Sie das Ergebnis mit der ersten Tabelle vergleichen, können Sie sehen, dass der Eintrag für den 23. und 31. aus den Ergebnissen gelöscht wurde, da er null war.

Andere, die eine Prozedur oder eine union-Anweisung erstellen. Was wäre die eleganteste Lösung?

Danke.

+2

Verarbeiten fehlender Daten im Anwendungscode. Und NIEMALS eine GROUP BY-Klausel in eine Abfrage einfügen, die keine Aggregationsfunktionen enthält. Es ist ein sicherer Weg, unsinnige Ergebnismengen zurückzugeben. – Strawberry

+0

Nun kann ich eine Zählung hinzufügen, das gleiche Ergebnis ... –

+0

Ja. Immer noch unsinnig! – Strawberry

Antwort

0

Lassen Sie uns zuerst die Daten erhalten:

select dt 
from calendar_table 
where dt between date_add(curdate(), interval -14 day) and curdate(); 

Dann werden die Benutzer:

select distinct user from backupdetail; 

Wenn Sie eine Benutzer-Tabelle haben (wie Sie haben sollten) Sie stattdessen die Benutzer aus dieser Tabelle wählen würde Na sicher.

Dann lassen Sie uns den Status pro Tag und Benutzer erhalten:

select user, date, group_concat(distinct status order by status) as statuses 
from backupdetail 
group by user, date; 

Wenn Sie daran interessiert sind nur in status = 'Erfolg', können Sie natürlich diese machen eine bloße:

select distinct user, date, status 
from backupdetail 
where status = 'Success'; 

Jetzt join: Zuerst erstellen Sie alle Kombinationen von Daten und Benutzern (CROSS JOIN), dann äußere die vorhandenen Backupdetail-Datensätze.

SELECT 
c.dt, 
u.user, 
COALESCE(b.status, 'NO DATA') as status 
FROM 
(
    select dt 
    from calendar_table 
    where dt between date_add(curdate(), interval -14 day) and curdate() 
) c 
CROSS JOIN (select distinct user from backupdetail) u 
LEFT JOIN 
(
    select distinct user, date, status 
    from backupdetail 
    where status = 'Success' 
) b ON b.user = u.user AND date(b.date) = c.dt 
ORDER BY c.dt, u.user; 
+0

Brilliant Danke Thorsten. –