Comment puis-je améliorer mon instruction SQL avec des résultats hebdomadaires avec la semaine à partir de jeudi ou tout autre jour de la semaine?

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

  •  16-10-2019
  •  | 
  •  

Question

Je suis un newb total et je ne pouvais pas trouver une bonne façon de le faire partout. J'ai une table de base de données qui contient des statistiques qui sont enregistrées à différents moments tout au long de la semaine. La semaine de déclaration commence jeudi. Le tableau contient une colonne datestamp (date) qui stocke lorsque les données ont été enregistrées.

Je dois extraire les données pour une semaine donnée (semaines de déclaration commencent le jeudi). Je l'ai écrit la requête suivante:

   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

Cela semble travailler sur les tests initiaux. Mais je ne suis pas sûr qu'il est la meilleure façon de s'y prendre. Je ne sais pas beaucoup sur les performances de MySQL, mais il y aura plus de cent mille enregistrements à filtrer. Est-ce que cette requête soit très lentement en raison du nombre de conditions vérifiées?

Le NOW () fonction est utilisée lorsque l'on tire le plus courant Report- cependant, il certains cas, je devrai faire des rapports pour d'autres semaines- donc je remplacer une autre date dans le lieu.

, il fait aussi de cette façon nécessite une nouvelle rédaction de la requête si la semaine de rapports Changes- dire les changements de jour à partir de mercredi.

Je ne peux pas utiliser la fonction WEEK () parce que vous ne pouvez commencer une semaine sur dim ou lun avec elle.

Toutes les idées pour améliorer cette requête sont très appréciés!

Autres Notes:. À l'heure actuelle à l'aide MariaDB 5.3

Était-ce utile?

La solution

Voici une requête que j'ai écrit pour vous donner le jeudi dernier et se termine mercredi

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;

Voici un exemple pour aujourd'hui, 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)

Il suffit de remplacer les appels de fonction NOW () avec tout ce que vous DateTime comme et vous aurez la semaine à partir de jeudi tout le temps pour le datetime donner de votre choix.

Voici un autre exemple en utilisant la date spécifique '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)

Votre requête de référencement table aujourd'hui ressemblerait à quelque chose comme ceci:

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;

Lui donner un essai !!!

Mise à jour 2011-09-22 16:27 EDT

Ce fut ma requête proposée pour marquer Jeu-MER.

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;

Que diriez-vous d'autres semaines ???

  • (SELECT SUBSTR('6012345',wkndx,1) fait la semaine à partir de fin Mon Soleil
  • (SELECT SUBSTR('5601234',wkndx,1) fait la semaine à partir de fin mar Mon
  • (SELECT SUBSTR('4560123',wkndx,1) fait la semaine à partir de fin Mer Mar
  • (SELECT SUBSTR('3456012',wkndx,1) fait la semaine à partir de fin jeu mer
  • (SELECT SUBSTR('2345601',wkndx,1) fait la semaine à partir de fin ven jeu
  • (SELECT SUBSTR('1234560',wkndx,1) fait la semaine à partir de fin Sam VEN.
  • (SELECT SUBSTR('0123456',wkndx,1) fait la semaine à partir de fin Sun Sat

Autres conseils

Permettez-moi de répéter ce que vous demandez pour vous assurer que je reçois ce droit:

Vous voulez tirer tous les records pour les 7 derniers jours une date précise?

Il pourrait ressembler à:

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

Il est important de noter que la date $ n'est pas littérale syntaxe de MySQL, mais juste un exemple support de place pour la date de début de votre choix. Si cela est pour signaler que j'imagine la requête sera finalement générée à partir un script? Si cela est vrai, il pourrait être plus simple dans cette langue et de passer ensuite dans la valeur littérale dans le cadre de la requête construite.

Je suis fan de requêtes garder aussi simple que possible donc je laisse comme ça. Je vais laisser la place aux autres pour apporter des réponses à accomplir ce que vous voulez dans une seule requête SQL-fu.

Modifier Après avoir relu votre message, il semble que vous utilisez probablement le type de date. Dans ce cas, le bloc suivant en italique peut être redondant. Je pars dans le cas où il est utile pour les autres (et depuis que je pris le temps de l'écrire: -)

Vous avez dit que vous utilisez un "datestamp"? Ce n'est pas techniquement un type de table. Est-ce un datetime, l'horodatage ou la date (heure et l'année, mais Existent aussi de votre contexte, je sens ce ne sont pas applicables)? Je demande parce que vous peut veulent faire juste une colonne de date au lieu des autres. Si tel est le bon choix pour vous dépend vraiment sur les détails de la façon dont l'columnn est utilisé et la table interrogée sur tout. Si elle est le seul but est juste pour les enregistrements de traction dans une plage de dates, quel que soit le temps, alors la date est certainement le chemin à parcourir. D'une part, il ne fallait 3 octets au lieu de 4 ou 8. Je peux élaborer sur d'autres raisons que vous voudriez à ce jour d'utilisation si elle correspond à vos besoins d'utilisation (à savoir que vous ne se soucient pas de la partie du temps). Vous trouverez plus de détails sur les différents types à http://dev.mysql.com/doc/refman/5.0/en /datetime.html

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

Si et seulement si vous utilisez la date que vous pourriez spécifiquement considérer les points suivants:

Exécuter la requête avec préfixés par « expliquer ». Les détails sur la façon d'interpréter la sortie et ce qui est le mieux peut être trouvé à http://dev.mysql.com/doc/refman/5.0/en/explain-output.html

Une fois que vous avez qui expliquent changer la requête à

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

où vous énumérez toutes les dates individuelles qui vous intéressent. Je suis venu dans des situations où il est évident MySQL est pas assez intelligent pour effecitvely utiliser une requête de gamme (entre x et y) vers l'énumération des valeurs spécifiques pour les petits ensembles.

Quelle que soit le cas d'utilisation, vous voulez vous assurer que la colonne est indexée si vous effectuez des requêtes de rapports réguliers en fonction de ses valeurs.

M. @Rolando répond évidemment à la question, mais je vais proposer une autre décision qui vous permettra de manipuler et personnaliser des calendriers entre les fuseaux horaires et plus important groupe de semaines qui sont définies dans des fuseaux horaires différents

, supposons que votre mySQL est en cours d'exécution sur le serveur configuré UTC et vous voulez avoir un calendrier personnalisé qui est de 7 heures à l'avance et par conséquent vos semaines devraient commencer le samedi 7 heures

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);

cartésien populaire qui devrait se joindre à remplir votre table:

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;

Permet de mettre à jour les heures:

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

et enfin organiser de manière personnalisée la semaine de votre calendrier

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));

Croyez-moi que je passe quelques heures à venir avec cette décision, mais il vous donne tant de liberté dans le cas où vous voulez regrouper vos résultats en fonction d'un fuseau horaire personnalisé et définitions semaine.

Licencié sous: CC-BY-SA avec attribution
Non affilié à dba.stackexchange
scroll top