9 Stimmen

SQL: Wo zwischen zwei Daten ohne Jahr?

Ich versuche, historische Daten abzufragen, und ich muss Daten nur aus einem 1-Monats-Zeitraum zurückgeben: 2 Wochen zurück und 2 Wochen vorwärts, aber ich brauche das Jahr, um keine Rolle.

Wenn ich also die Abfrage heute machen würde, würde ich alle Zeilen mit date zwischen xxxx-06-31 und xxxx-07-27

Vielen Dank im Voraus für die Hilfe!

EDIT: Ich habe zwei Möglichkeiten ausprobiert, von denen ich glaube, dass beide nicht um das neue Jahr herum funktionieren werden. Eine ist es, datepart(day) zu verwenden und die andere wäre, einfach das Jahr aus dem Datum zu nehmen und zu vergleichen.

9voto

mdahlman Punkte 9009

Der beste Weg, sich dieses Problem vorzustellen, ist, die Daten in eine Zahl zwischen 0 und 365 umzuwandeln, die dem Tag im Jahr entspricht. Wählen Sie dann einfach Daten aus, bei denen diese Differenz weniger als 14 beträgt, und Sie erhalten Ihr Zwei-Wochen-Fenster.

Das wird am Anfang oder am Ende des Jahres zusammenbrechen. Aber einfache modulare Arithmetik gibt Ihnen die Antwort.

Glücklicherweise hat MySQL DAYOFYEAR(date) Es ist also nicht so kompliziert:

SELECT * FROM tbl t
WHERE 
  MOD(DAYOFYEAR(currdate) - DAYOFYEAR(t.the_date) + 365, 365) <= 14
  OR MOD(DAYOFYEAR(t.the_date) - DAYOFYEAR(currdate) + 365, 365) <= 14

Dieses Extra + 365 ist erforderlich, da MySQLs MOD negative Zahlen zurückgibt.

Bei dieser Antwort werden die Schaltjahre nicht korrekt berücksichtigt. Wenn das aktuelle Jahr kein Schaltjahr ist und das aktuelle Datum innerhalb von 14 Tagen nach dem Jahresende liegt, fehlt ein Tag im Januar, den Sie hätten einbeziehen müssen. Wenn Ihnen das wichtig ist, sollten Sie Folgendes ersetzen 365 con [the number of days in the year - 1 ].

7voto

John Woo Punkte 249233

Angenommen, Sie haben eine Verabredung wie diese,

create table datelist
(
  d date
);

insert into datelist values
('2012-07-01'),
('2011-06-29'),
('2012-07-02'),
('2010-07-05'),
('2012-05-31'),
('2010-06-30');

Probieren Sie die folgende Abfrage aus,

SELECT d, date_format(d,'%Y-%b-%d')
FROM datelist
WHERE (MONTH(d) = 6 AND DAYOFMONTH(d) >= 30)
   OR (MONTH(d) = 7 AND DAYOFMONTH(d) <= 27)

SQLFiddle-Demo

2voto

pilcrow Punkte 53851

Ist es in Ordnung, wenn die Lösung furchtbar langsam ist?

    SELECT tbl.*
      FROM tbl
INNER JOIN (SELECT COALESCE(DATE(CONCAT(yyyy, '-', MONTH(CURRENT_DATE), '-', DAYOFMONTH(CURRENT_DATE)),
                            DATE(CONCAT(yyyy, '-02-28'))) AS midpoint
              FROM (SELECT DISTINCT(YEAR(d)) AS yyyy
                     FROM tbl) all_years) adjusted
           ON tbl.datecol BETWEEN adjusted.midpoint - INTERVAL 2 WEEK
                                  AND
                                  adjusted.midpoint + INTERVAL 2 WEEK;

Das berechnet alle Mittelpunkte für alle Jahre im Datensatz und zieht dann Datensätze +- 2 Wochen von jedem dieser Mittelpunkte, was den Jahresendumbruch behandelt.

COALESCE behandelt den 29.02. in Jahren ohne Schalttag (den MySQL NULL-ifizieren wird) und zwingt ihn auf den 28.02. herunter.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X