Wie kann ich meine SQL-Anweisung mit wöchentlichen Ergebnissen verbessern, wobei die Woche am Donnerstag oder einem anderen Wochentag beginnt?

dba.stackexchange https://dba.stackexchange.com/questions/6045

  •  16-10-2019
  •  | 
  •  

Frage

Ich bin ein absoluter Neuling und konnte nirgendwo eine gute Möglichkeit finden, dies zu tun.Ich habe eine Datenbanktabelle, die Statistiken enthält, die zu verschiedenen Zeiten im Laufe der Woche aufgezeichnet werden.Die Berichtswoche beginnt am Donnerstag.Die Tabelle enthält eine Datumsstempelspalte (Datum), die speichert, wann die Daten aufgezeichnet wurden.

Ich muss die Daten für eine bestimmte Woche abrufen (die Berichtswochen beginnen am Donnerstag).Ich habe die folgende Abfrage geschrieben:

   SELECT * 
FROM `table` 
WHERE 1 = CASE 
  WHEN WEEKDAY(NOW()) = 0 THEN DATEDIFF(NOW(),`date`) BETWEEN -2 AND 4
  WHEN WEEKDAY(NOW()) = 1 THEN DATEDIFF(NOW(),`date`) BETWEEN -1 AND 5
  WHEN WEEKDAY(NOW()) = 2 THEN DATEDIFF(NOW(),`date`) BETWEEN -0 AND 6
  WHEN WEEKDAY(NOW()) = 3 THEN DATEDIFF(NOW(),`date`) BETWEEN -6 AND 0
  WHEN WEEKDAY(NOW()) = 4 THEN DATEDIFF(NOW(),`date`) BETWEEN -5 AND 1
  WHEN WEEKDAY(NOW()) = 5 THEN DATEDIFF(NOW(),`date`) BETWEEN -4 AND 2
  WHEN WEEKDAY(NOW()) = 6 THEN DATEDIFF(NOW(),`date`) BETWEEN -3 AND 3
END

Dies scheint bei ersten Tests zu funktionieren.Aber ich bin mir nicht sicher, ob das der beste Weg ist.Ich weiß nicht viel über die Leistung von MySQL, aber es müssen über hunderttausend Datensätze gefiltert werden.Wird diese Abfrage aufgrund der Anzahl der überprüften Bedingungen sehr langsam sein?

Die Funktion NOW() wird verwendet, wenn der aktuellste Bericht abgerufen wird. In einigen Fällen muss ich jedoch Berichte für andere Wochen erstellen, sodass ich die Stelle durch ein anderes Datum ersetzen würde.

Außerdem muss bei dieser Vorgehensweise die Abfrage neu geschrieben werden, wenn sich die Berichtswoche ändert, beispielsweise wenn sich der Starttag auf Mittwoch ändert.

Ich kann die Funktion WEEK() nicht verwenden, da man damit eine Woche nur am Sonntag oder Montag beginnen kann.

Alle Ideen zur Verbesserung dieser Abfrage sind sehr willkommen!

Weitere Hinweise:Derzeit wird MariaDB 5.3 verwendet.

War es hilfreich?

Lösung

Hier ist eine Frage, die ich geschrieben habe, um Ihnen den letzten Donnerstag und den Ende am Mittwoch zu geben

SELECT thuwk_beg + INTERVAL 0 second thu_beg,
thuwk_beg + INTERVAL 604799 second wed_end
FROM (SELECT (DATE(NOW()) - INTERVAL daysbacktothursday DAY) thuwk_beg
FROM (SELECT SUBSTR('3456012',wkndx,1) daysbacktothursday
FROM (SELECT DAYOFWEEK(dt) wkndx FROM (SELECT DATE(NOW()) dt) AAAA) AAA) AA) A;

Hier ist ein Beispiel für heute, 2011-09-21

mysql> SELECT
    -> thuwk_beg + INTERVAL 0 second thu_beg,
    -> thuwk_beg + INTERVAL 604799 second wed_end
    -> FROM (SELECT (DATE(NOW()) - INTERVAL daysbacktothursday DAY) thuwk_beg
    -> FROM (SELECT SUBSTR('3456012',wkndx,1) daysbacktothursday
    -> FROM (SELECT DAYOFWEEK(dt) wkndx FROM (SELECT DATE(NOW()) dt) AAAA) AAA) AA) A;
+---------------------+---------------------+
| thu_beg             | wed_end             |
+---------------------+---------------------+
| 2011-09-15 00:00:00 | 2011-09-21 23:59:59 |
+---------------------+---------------------+
1 row in set (0.00 sec)

Ersetzen Sie einfach die Funktionsanrufe von NOW () durch die mögliche DateTime, und Sie werden die Woche ab Donnerstag für die gewählte Gebendatenbezeichnung haben.

Hier ist ein weiteres Beispiel mit dem spezifischen Datum "2011-01-01"

mysql> SELECT
    -> thuwk_beg + INTERVAL 0 second thu_beg,
    -> thuwk_beg + INTERVAL 604799 second wed_end
    -> FROM (SELECT (DATE('2011-01-01') - INTERVAL daysbacktothursday DAY) thuwk_beg
    -> FROM (SELECT SUBSTR('3456012',wkndx,1) daysbacktothursday
    -> FROM (SELECT DAYOFWEEK(dt) wkndx FROM (SELECT DATE('2011-01-01') dt) AAAA) AAA) AA) A;
+---------------------+---------------------+
| thu_beg             | wed_end             |
+---------------------+---------------------+
| 2010-12-30 00:00:00 | 2011-01-05 23:59:59 |
+---------------------+---------------------+
1 row in set (0.00 sec)

Ihre Frage von table Das Verweisen heute würde so etwas ähneln:

SELECT * from `table`,
(SELECT thuwk_beg + INTERVAL 0 second thu_beg,
thuwk_beg + INTERVAL 604799 second wed_end
FROM (SELECT (DATE(NOW()) - INTERVAL daysbacktothursday DAY) thuwk_beg
FROM (SELECT SUBSTR('3456012',wkndx,1) daysbacktothursday
FROM (SELECT DAYOFWEEK(dt) wkndx FROM (SELECT DATE(NOW()) dt) AAAA) AAA) AA) A) M
WHERE `date` >= thu_beg
AND `date` <= wed_end;

Versuche es !!!

Update 2011-09-22 16:27 EDT

Dies war meine geplante Anfrage zur Markierung von Do-Bed.

SELECT thuwk_beg + INTERVAL 0 second thu_beg,
thuwk_beg + INTERVAL 604799 second wed_end
FROM (SELECT (DATE(NOW()) - INTERVAL daysbacktothursday DAY) thuwk_beg
FROM (SELECT SUBSTR('3456012',wkndx,1) daysbacktothursday
FROM (SELECT DAYOFWEEK(dt) wkndx FROM (SELECT DATE(NOW()) dt) AAAA) AAA) AA) A;

Wie wäre es mit anderen Wochen ???

  • (SELECT SUBSTR('6012345',wkndx,1) Fängt die Woche an, die Mon Mon End Sonne beginnt?
  • (SELECT SUBSTR('5601234',wkndx,1) Fängt die Woche an, die Mons endet?
  • (SELECT SUBSTR('4560123',wkndx,1) Ist die Woche, die mit dem Mittwoch endet?
  • (SELECT SUBSTR('3456012',wkndx,1) versteht die Woche, die du endete?
  • (SELECT SUBSTR('2345601',wkndx,1) beginnt die Woche, in der Fr endet?
  • (SELECT SUBSTR('1234560',wkndx,1) Ist die Woche begonnen, um zu enden
  • (SELECT SUBSTR('0123456',wkndx,1) Saß die Woche, die die Sonne endet?

Andere Tipps

Lassen Sie mich noch einmal wiederholen, was Sie verlangen, um sicherzugehen, dass ich es richtig mache:

Sie möchten alle Datensätze der letzten 7 Tage zu einem bestimmten Datum abrufen?

Es könnte so aussehen:

select * from table where `date` between $date - interval 7 day and $date

Es ist wichtig zu beachten, dass es sich bei $date nicht um eine wörtliche MySQL-Syntax handelt, sondern lediglich um einen Beispielplatzhalter für das gewünschte Startdatum.Wenn dies zur Berichterstellung dient, kann ich mir vorstellen, dass die Abfrage letztendlich aus einem Skript generiert wird?Wenn das zutrifft, könnte es in dieser Sprache einfacher sein, den Literalwert als Teil der konstruierten Abfrage zu übergeben.

Ich bin ein Fan davon, Abfragen so einfach wie möglich zu halten, deshalb würde ich es dabei belassen.Ich lasse anderen Raum, Antworten beizutragen, um in einer einzigen SQL-Fu-Abfrage das zu erreichen, was Sie wollen.

Bearbeiten: Nachdem ich Ihren Beitrag noch einmal gelesen habe, scheint es, dass Sie wahrscheinlich den Datumstyp verwenden.In diesem Fall ist der folgende kursiv gedruckte Block möglicherweise überflüssig.Ich lasse es für den Fall, dass es für andere hilfreich ist (und da ich mir die Zeit genommen habe, es zu schreiben :-)

Sie sagten, Sie verwenden einen „Datumsstempel“?Das ist technisch gesehen kein MySQL-Datentyp.Handelt es sich um eine Datums-/Uhrzeitangabe, einen Zeitstempel oder ein Datum (Zeit und Jahr existieren ebenfalls, aber aus Ihrem Kontext bin ich der Meinung, dass diese nicht anwendbar sind)?Ich frage, weil du Mai Ich möchte es anstelle der anderen nur zu einer Datumsspalte machen.Ob dies die richtige Wahl für Sie ist, hängt wirklich von den Details der Verwendung der Spalte und der insgesamt abgefragten Tabelle ab.Wenn der einzige Zweck nur darin besteht, Datensätze in einem Datumsbereich abzurufen, unabhängig von der Uhrzeit, dann ist Datum definitiv die richtige Wahl.Zum einen waren nur 3 statt 4 oder 8 Bytes erforderlich.Ich kann weitere Gründe erläutern, warum Sie das Datum verwenden möchten, wenn es Ihren Nutzungsanforderungen entspricht (z. B.Der Zeitanteil ist Ihnen egal).Details zu den verschiedenen Typen finden Sie unterhttp://dev.mysql.com/doc/refman/5.0/en/datetime.html

http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html

Wenn Sie speziell das Datum verwenden, sollten Sie Folgendes in Betracht ziehen:

Führen Sie die Abfrage mit dem Präfix „explain“ aus.Einzelheiten zur Interpretation der Ausgabe und was am besten ist, finden Sie unter http://dev.mysql.com/doc/refman/5.0/en/explain-output.html

Sobald Sie die Erklärung haben, ändern Sie die Abfrage in „

select * from table where date in ("N", "N+1"..."N+7")

Hier listen Sie alle Einzeltermine auf, die Sie interessieren.Ich bin auf Situationen gestoßen, in denen klar war, dass MySQL nicht intelligent genug ist, um eine Bereichsabfrage effektiv zu verwenden (d. h.zwischen x und y) Verse, die spezifische Werte für kleine Mengen aufzählen.

Unabhängig vom Anwendungsfall sollten Sie sicherstellen, dass die Spalte indiziert ist, wenn Sie regelmäßige Berichtsabfragen auf der Grundlage ihrer Werte durchführen.

Mr @rolando beantwortet offensichtlich die Frage, aber ich werde eine andere Entscheidung vorschlagen, mit der Sie Kalender zwischen Timezones und wichtigsten Gruppen um Wochen manipulieren und anpassen können, die in verschiedenen Zeitzonen definiert sind

Nehmen wir also an, dass Ihr MySQL auf UTC -konfigurierter Server ausgeführt wird und Sie einen benutzerdefinierten Kalender haben möchten, der 7 Stunden im Voraus liegt. Daher sollten Ihre Wochen am Samstag, den 7.00 Uhr beginnen, beginnen

CREATE TABLE `wh_blur_calendar` (
  `date` timestamp NOT NULL ,
  `y` smallint(6) DEFAULT NULL,
  `q` tinyint(4) DEFAULT NULL,
  `m` tinyint(4) DEFAULT NULL,
  `d` tinyint(4) DEFAULT NULL,
  `w` tinyint(4) DEFAULT NULL,
  PRIMARY KEY (`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `wh_ints` (
  `i` tinyint(4) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into wh_ints values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

Jetzt ein beliebter kartesischer Anschluss, der Ihren Tisch füllen sollte:

INSERT INTO wh_blur_calendar (date)
SELECT DATE('2010-01-01 00:00:00 ') + INTERVAL a.i*10000 + b.i*1000 + c.i*100 + d.i*10 + e.i DAY
FROM wh_ints a JOIN wh_ints b JOIN wh_ints c JOIN wh_ints d JOIN wh_ints e
WHERE (a.i*10000 + b.i*1000 + c.i*100 + d.i*10 + e.i) < 10245
ORDER BY 1;

Lassen Sie uns die Stunden aktualisieren:

update  db_wh_repo.wh_blur_calendar set date = date_add(date, interval 7 hour);

und arrangieren Sie schließlich die Woche Ihres Kalenders auf kundenspezifische Weise

UPDATE wh_blur_calendar
SET 
    y = YEAR(date),
    q = quarter(date),
    m = MONTH(date),
    d = dayofmonth(date),
    w = week(date_add((date), interval 1 day));

Glauben Sie mir, ich verbringe einige Stunden damit, diese Entscheidung zu treffen, aber sie gibt Ihnen so viel Freiheit, falls Sie Ihre Ergebnisse basierend auf einer benutzerdefinierten Zeitzone- und Wochen-Definitionen gruppieren möchten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit dba.stackexchange
scroll top