générer des jours à partir de la plage de dates

j'aimerais lancer une requête comme

select ... as days where `date` is between '2010-01-20' and '2010-01-24'

et retourner des données comme:

days
----------
2010-01-20
2010-01-21
2010-01-22
2010-01-23
2010-01-24
118
demandé sur Pentium10 2010-01-28 22:21:44

23 réponses

Cette solution utilise des pas de boucles, procédures, ou de tables temporaires . Le sous-jeu génère des dates pour les derniers mille jours, et peut être prolongé pour aller aussi loin en arrière ou en avant que vous le souhaitez.

select a.Date 
from (
    select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
    from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) a
where a.Date between '2010-01-20' and '2010-01-24' 

sortie:

Date
----------
2010-01-24
2010-01-23
2010-01-22
2010-01-21
2010-01-20

Notes sur les performances

Tester ici , la performance est étonnamment bonne: la requête ci-dessus prend 0.0009 sec.

si nous étendons le sous-jeu pour générer environ. 100.000 nombres (et donc environ 274 années de valeur des dates), il court en 0.0458 sec.

incidemment, il s'agit d'une technique très portable qui fonctionne avec la plupart des bases de données avec des ajustements mineurs.

SQL Violon exemple de retour de 1 000 jours

284
répondu RedFilter 2012-05-30 17:07:55

Voici une autre variation utilisant des vues:

CREATE VIEW digits AS
  SELECT 0 AS digit UNION ALL
  SELECT 1 UNION ALL
  SELECT 2 UNION ALL
  SELECT 3 UNION ALL
  SELECT 4 UNION ALL
  SELECT 5 UNION ALL
  SELECT 6 UNION ALL
  SELECT 7 UNION ALL
  SELECT 8 UNION ALL
  SELECT 9;

CREATE VIEW numbers AS
  SELECT
    ones.digit + tens.digit * 10 + hundreds.digit * 100 + thousands.digit * 1000 AS number
  FROM
    digits as ones,
    digits as tens,
    digits as hundreds,
    digits as thousands;

CREATE VIEW dates AS
  SELECT
    SUBDATE(CURRENT_DATE(), number) AS date
  FROM
    numbers;

et puis vous pouvez simplement faire (voyez comme il est élégant?):

SELECT
  date
FROM
  dates
WHERE
  date BETWEEN '2010-01-20' AND '2010-01-24'
ORDER BY
  date

mise à Jour

il est intéressant de noter que vous ne pourrez générer dates passées à partir de la date actuelle . Si vous voulez générer n'importe quel type de gamme de dates (passées, futures, et entre), vous devrez utiliser cette vue à la place:

CREATE VIEW dates AS
  SELECT
    SUBDATE(CURRENT_DATE(), number) AS date
  FROM
    numbers
  UNION ALL
  SELECT
    ADDDATE(CURRENT_DATE(), number + 1) AS date
  FROM
    numbers;
30
répondu Stéphane 2013-12-22 21:08:29

Accepté de répondre ne fonctionne pas pour PostgreSQL (erreur de syntaxe sur ou près de "a").

la façon dont vous faites ceci dans PostgreSQL est en utilisant generate_series fonction, i.e.:

SELECT day::date
FROM generate_series('2010-01-20', '2010-01-24', INTERVAL '1 day') day;

    day
------------
 2010-01-20
 2010-01-21
 2010-01-22
 2010-01-23
 2010-01-24
(5 rows)
18
répondu Dmitry Gusev 2015-07-05 12:21:11

en utilisant une Expression de table commune récursive (CTE), vous pouvez générer une liste de dates, puis sélectionner à partir de celle-ci. Évidemment, vous ne voulez pas créer trois millions de dates, donc cela illustre juste les possibilités. Vous pouvez simplement limiter la plage de dates à l'intérieur du CTE et omettre la clause where de la déclaration select en utilisant le cte.

with [dates] as (
    select convert(datetime, '1753-01-01') as [date] --start
    union all
    select dateadd(day, 1, [date])
    from [dates]
    where [date] < '9999-12-31' --end
)
select [date]
from [dates]
where [date] between '2013-01-01' and '2013-12-31'
option (maxrecursion 0)

sur Microsoft SQL Server 2005, générant la liste CTE de toutes les dates possibles a pris 1:08. Générer un cent ans ont pris moins d'une seconde.

12
répondu Joshua 2017-04-03 07:06:20

MSSQL Query

select datetable.Date 
from (
    select DATEADD(day,-(a.a + (10 * b.a) + (100 * c.a)),getdate()) AS Date
    from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4
     union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a

    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4
     union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b

    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4
     union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) datetable
where datetable.Date between '2014-01-20' and '2014-01-24' 
order by datetable.Date DESC

sortie

Date
-----
2014-01-23 12:35:25.250
2014-01-22 12:35:25.250
2014-01-21 12:35:25.250
2014-01-20 12:35:25.250
7
répondu SUHAIL AG 2014-09-28 08:41:15

la solution de l'ancienne école pour faire cela sans boucle/curseur est de créer une table NUMBERS , qui a une colonne entière unique avec des valeurs commençant à 1.

CREATE TABLE  `example`.`numbers` (
  `id` int(10) unsigned NOT NULL auto_increment,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

vous devez remplir la table avec assez de disques pour couvrir vos besoins:

INSERT INTO NUMBERS (id) VALUES (NULL);

une fois que vous avez la table NUMBERS , vous pouvez utiliser:

SELECT x.start_date + INTERVAL n.id-1 DAY
  FROM NUMBERS n
  JOIN (SELECT STR_TO_DATE('2010-01-20', '%Y-%m-%d') AS start_date 
          FROM DUAL) x
 WHERE x.start_date + INTERVAL n.id-1 DAY <= '2010-01-24'

L'absolu low-tech solution serait:

SELECT STR_TO_DATE('2010-01-20', '%Y-%m-%d')
 FROM DUAL
UNION ALL
SELECT STR_TO_DATE('2010-01-21', '%Y-%m-%d')
 FROM DUAL
UNION ALL
SELECT STR_TO_DATE('2010-01-22', '%Y-%m-%d')
 FROM DUAL
UNION ALL
SELECT STR_TO_DATE('2010-01-23', '%Y-%m-%d')
 FROM DUAL
UNION ALL
SELECT STR_TO_DATE('2010-01-24', '%Y-%m-%d')
 FROM DUAL

pour quoi l'utiliseriez-vous?


pour générer des listes de dates ou de numéros afin de rejoindre left on. Vous le feriez pour voir où il y a des lacunes dans les données, parce que vous êtes laissé se joindre à une liste de données séquentielles - les valeurs null rendront évident où des lacunes existent.

4
répondu OMG Ponies 2010-01-28 19:51:00

pour Access 2010 - plusieurs étapes nécessaires; j'ai suivi le même modèle que celui affiché ci-dessus, mais j'ai pensé que je pourrais aider quelqu'un dans Access. Ça a bien marché pour moi, je n'ai pas eu besoin de garder une table de dates.

créer une table appelée DUAL (similaire au fonctionnement de la table Dual D'Oracle)

  • ID (AutoNumber)
  • DummyColumn (Text)
  • ajouter une ligne (1,"DummyRow")

créer une requête appelée "ZeroThru9Q"; entrer manuellement la syntaxe suivante:

SELECT 0 AS a
FROM dual
UNION ALL
SELECT 1
FROM dual
UNION ALL
SELECT 2
FROM dual
UNION ALL
SELECT 3
FROM dual
UNION ALL
SELECT 4
FROM dual
UNION ALL
SELECT 5
FROM dual
UNION ALL
SELECT 6
FROM dual
UNION ALL
SELECT 7
FROM dual
UNION ALL
SELECT 8
FROM dual
UNION ALL
SELECT 9
FROM dual;

créer une requête appelée "TodayMinus1KQ" (pour les dates avant aujourd'hui); entrer manuellement la syntaxe suivante:

SELECT date() - (a.a + (10 * b.a) + (100 * c.a)) AS MyDate
FROM
  (SELECT *
   FROM ZeroThru9Q) AS a,

  (SELECT *
   FROM ZeroThru9Q) AS b,

  (SELECT *
   FROM ZeroThru9Q) AS c

créer une requête appelée "TodayPlus1KQ" (pour les dates après aujourd'hui); entrer manuellement la syntaxe suivante:

SELECT date() + (a.a + (10 * b.a) + (100 * c.a)) AS MyDate
FROM
  (SELECT *
   FROM ZeroThru9Q) AS a,

  (SELECT *
   FROM ZeroThru9Q) AS b,

  (SELECT *
   FROM ZeroThru9Q) AS c;

créer une requête d'union nommée " TodayPlusMinus1KQ" (pour les dates +/- 1000 jours):

SELECT MyDate
FROM TodayMinus1KQ
UNION
SELECT MyDate
FROM TodayPlus1KQ;

Maintenant, vous pouvez utiliser la requête:

SELECT MyDate
FROM TodayPlusMinus1KQ
WHERE MyDate BETWEEN #05/01/2014# and #05/30/2014#
4
répondu Travis 2015-08-25 19:27:24

thx Pentium10-vous m'avez fait rejoindre stackoverflow :) - c'est mon portage vers msaccess - je pense que ça marchera sur n'importe quelle version:

SELECT date_value
FROM (SELECT a.espr1+(10*b.espr1)+(100*c.espr1) AS integer_value,
dateadd("d",integer_value,dateserial([start_year], [start_month], [start_day])) as date_value
FROM (select * from 
    (
    select top 1 "0" as espr1 from MSysObjects
    union all
    select top 1 "1" as espr2 from MSysObjects
    union all
    select top 1 "2" as espr3 from MSysObjects
    union all
    select top 1 "3" as espr4 from MSysObjects
    union all
    select top 1 "4" as espr5 from MSysObjects
    union all
    select top 1 "5" as espr6 from MSysObjects
    union all
    select top 1 "6" as espr7 from MSysObjects
    union all
    select top 1 "7" as espr8 from MSysObjects
    union all
    select top 1 "8" as espr9 from MSysObjects
    union all
    select top 1 "9" as espr9 from MSysObjects
    ) as a,
    (
    select top 1 "0" as espr1 from MSysObjects
    union all
    select top 1 "1" as espr2 from MSysObjects
    union all
    select top 1 "2" as espr3 from MSysObjects
    union all
    select top 1 "3" as espr4 from MSysObjects
    union all
    select top 1 "4" as espr5 from MSysObjects
    union all
    select top 1 "5" as espr6 from MSysObjects
    union all
    select top 1 "6" as espr7 from MSysObjects
    union all
    select top 1 "7" as espr8 from MSysObjects
    union all
    select top 1 "8" as espr9 from MSysObjects
    union all
    select top 1 "9" as espr9 from MSysObjects
    ) as b,
    (
    select top 1 "0" as espr1 from MSysObjects
    union all
    select top 1 "1" as espr2 from MSysObjects
    union all
    select top 1 "2" as espr3 from MSysObjects
    union all
    select top 1 "3" as espr4 from MSysObjects
    union all
    select top 1 "4" as espr5 from MSysObjects
    union all
    select top 1 "5" as espr6 from MSysObjects
    union all
    select top 1 "6" as espr7 from MSysObjects
    union all
    select top 1 "7" as espr8 from MSysObjects
    union all
    select top 1 "8" as espr9 from MSysObjects
    union all
    select top 1 "9" as espr9 from MSysObjects
    ) as c   
)  as d) 
WHERE date_value 
between dateserial([start_year], [start_month], [start_day]) 
and dateserial([end_year], [end_month], [end_day]);

MSysObjects référencés juste parce que l'accès a besoin d'une table comptant au moins 1 Enregistrement, dans une clause de from - n'importe quelle table avec au moins 1 Enregistrement ferait l'affaire.

3
répondu user3780177 2014-06-26 17:05:22

procédure + tableau temporaire:

DELIMITER $$

CREATE DEFINER=`root`@`localhost` PROCEDURE `days`(IN dateStart DATE, IN dateEnd DATE)
BEGIN

    CREATE TEMPORARY TABLE IF NOT EXISTS date_range (day DATE);

    WHILE dateStart <= dateEnd DO
      INSERT INTO date_range VALUES (dateStart);
      SET dateStart = DATE_ADD(dateStart, INTERVAL 1 DAY);
    END WHILE;

    SELECT * FROM date_range;
    DROP TEMPORARY TABLE IF EXISTS date_range;

END
2
répondu Márcio Souza Júnior 2014-06-12 15:32:16

essayez ceci.

SELECT TO_DATE('20160210','yyyymmdd') - 1 + LEVEL AS start_day 
from DUAL
connect by level <= (TO_DATE('20160228','yyyymmdd') + 1) - TO_DATE('20160210','yyyymmdd') ;
2
répondu loalexzzzz 2016-07-28 09:16:45

si vous avez besoin de plus de quelques jours, vous avez besoin d'un tableau.

créer une plage de dates dans mysql

puis,

select from days.day, count(mytable.field) as fields from days left join mytable on day=date where date between x and y;
1
répondu gcb 2017-05-23 11:33:24

comme indiqué (ou du moins fait allusion à) dans beaucoup des réponses merveilleuses déjà données, ce problème est facilement résolu une fois que vous avez un ensemble de nombres à travailler avec.

Note: ce qui suit est T-SQL mais c'est simplement mon implémentation particulière de concepts généraux déjà mentionnés ici et sur l'internet en général. Il devrait être relativement simple de convertir le code à votre dialecte de choix.

Comment? considérez cette requête:

SELECT DATEADD(d, N, '0001-01-22')
FROM Numbers -- A table containing the numbers 0 through N
WHERE N <= 5;

ce qui précède produit la plage de dates 1/22/0001 - 1/27/0001 et est extrêmement trivial. Il y a 2 informations clés dans la requête ci-dessus: la date de début de 0001-01-22 et le offset de 5 . Si nous combinons ces deux informations alors évidemment nous avons notre date de fin. Ainsi, étant donné deux dates, générant une gamme peut être décomposé comme:

  • trouver la différence entre deux dates données (le décalage), facile:

    -- Returns 125 SELECT ABS(DATEDIFF(d, '2014-08-22', '2014-12-25'))

    en utilisant ABS() ici assure que l'ordre de date n'est pas pertinent.

  • Générer un ensemble limité de numéros, aussi facile:

    -- Returns the numbers 0-2 SELECT N = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) - 1 FROM(SELECT 'A' AS S UNION ALL SELECT 'A' UNION ALL SELECT 'A')

    avis nous ne nous soucions pas réellement de ce que nous sélectionnons FROM ici. Nous avons juste besoin d'un ensemble à travailler avec ce que l'on compte le nombre de lignes. J'utilise personnellement un TVF, certains utilisent un CTE, d'autres utilisent une table de nombres à la place, vous avez l'idée. Je recommande d'utiliser la solution la plus performante que vous comprenez aussi.

la combinaison de ces deux méthodes résoudra notre problème:

DECLARE @date1 DATE = '9001-11-21';
DECLARE @date2 DATE = '9001-11-23';

SELECT D = DATEADD(d, N, @date1)
FROM (
    SELECT N = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) - 1
    FROM (SELECT 'A' AS S UNION ALL SELECT 'A' UNION ALL SELECT 'A') S
) Numbers
WHERE N <= ABS(DATEDIFF(d, @date1, @date2));

l'exemple ci-dessus est un code horrible mais montre comment tout réunir.

Plus De Plaisir

j'ai besoin de faire ce genre de chose beaucoup donc je encapsulé la logique en deux Tvf. La première génère une plage de nombres et la seconde utilise cette fonctionnalité pour générer une plage de dates. Le calcul est de s'assurer que l'ordre d'entrée n'importe pas et parce que je voulais utiliser la gamme complète des nombres disponibles dans GenerateRangeSmallInt .

La fonction suivante prend ~16ms de temps CPU pour retourner la plage maximale de 65536 dates.

CREATE FUNCTION dbo.GenerateRangeDate (   
    @date1 DATE,   
    @date2 DATE   
)   
RETURNS TABLE
WITH SCHEMABINDING   
AS   
RETURN (
    SELECT D = DATEADD(d, N + 32768, CASE WHEN @date1 <= @date2 THEN @date1 ELSE @date2 END)
    FROM dbo.GenerateRangeSmallInt(-32768, ABS(DATEDIFF(d, @date1, @date2)) - 32768)
);

GO

CREATE FUNCTION dbo.GenerateRangeSmallInt (
    @num1 SMALLINT = -32768
  , @num2 SMALLINT = 32767
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN (
    WITH Numbers(N) AS (
        SELECT N FROM(VALUES
            (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 16
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 32
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 48
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 64
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 80
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 96
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 112
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 128
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 144
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 160
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 176
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 192
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 208
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 224
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 240
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 256
        ) V (N)
    )
    SELECT TOP(ABS(CAST(@num1 AS INT) - CAST(@num2 AS INT)) + 1)
           N = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) + CASE WHEN @num1 <= @num2 THEN @num1 ELSE @num2 END - 1
    FROM Numbers A
       , Numbers B
);
1
répondu Kittoes0124 2014-08-25 14:25:06

générer des dates entre deux champs de date

si vous êtes au courant avec la requête SQL CTE, alors cette solution vous aidera à résoudre votre question

voici un exemple

nous avons des dates dans un tableau

nom de la Table:" testdate "

STARTDATE   ENDDATE
10/24/2012  10/24/2012
10/27/2012  10/29/2012
10/30/2012  10/30/2012

Exiger Le Résultat:

STARTDATE
10/24/2012
10/27/2012
10/28/2012
10/29/2012
10/30/2012

Solution:

WITH CTE AS
  (SELECT DISTINCT convert(varchar(10),StartTime, 101) AS StartTime,
                   datediff(dd,StartTime, endTime) AS diff
   FROM dbo.testdate
   UNION ALL SELECT StartTime,
                    diff - 1 AS diff
   FROM CTE
   WHERE diff<> 0)
SELECT DISTINCT DateAdd(dd,diff, StartTime) AS StartTime
FROM CTE

explication: CTE recursive query explication

  • première partie de la requête:



    SELECT DISTINCT convert(varchar(10), StartTime, 101) AS StartTime, datediff(dd, StartTime, endTime) AS diff FROM dbo.testdate



    Explication: la première colonne est "startdate", la deuxième colonne est la différence entre le début et la fin date en jours et il être considéré comme" diff "colonne

  • deuxième partie de la requête:



    UNION ALL SELECT StartTime, diff-1 AS diff FROM CTE WHERE diff<>0



    Explication: Union all héritera du résultat de la requête ci-dessus jusqu'à ce que le résultat soit null, Ainsi, le résultat" StartTime " est hériter de la requête CTE générée, et de diff, decrease-1, de sorte que son apparence ressemble à 3, 2, et 1 jusqu'à 0

par exemple

STARTDATE   DIFF
10/24/2012  0
10/27/2012  0
10/27/2012  1
10/27/2012  2
10/30/2012  0

Spécification De Résultat

STARTDATE       Specification
10/24/2012  --> From Record 1
10/27/2012  --> From Record 2
10/27/2012  --> From Record 2
10/27/2012  --> From Record 2
10/30/2012  --> From Record 3
  • 3ème partie de la requête



    SELECT DISTINCT DateAdd(dd,diff, StartTime) AS StartTime FROM CTE



    Il va ajouter jour "diff" dans "startdate" donc le résultat devrait être comme ci-dessous

résultat

STARTDATE
10/24/2012
10/27/2012
10/28/2012
10/29/2012
10/30/2012
1
répondu Tarun Harkinia 2015-08-25 19:27:45

réponse plus courte que acceptée, même idée:

(SELECT TRIM('2016-01-05' + INTERVAL a + b DAY) date
FROM
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3
UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7
UNION SELECT 8 UNION SELECT 9 ) d,
(SELECT 0 b UNION SELECT 10 UNION SELECT 20
UNION SELECT 30 UNION SELECT 40) m
WHERE '2016-01-05' + INTERVAL a + b DAY  <=  '2016-01-21')
1
répondu daniherculano 2016-01-21 09:23:39

pour quiconque veut ceci comme une vue sauvegardée (MySQL ne supporte pas les déclarations de sélection imbriquées dans les vues):

create view zero_to_nine as
    select 0 as n union all 
    select 1 union all 
    select 2 union all 
    select 3 union all 
    select 4 union all 
    select 5 union all 
    select 6 union all 
    select 7 union all 
    select 8 union all 
    select 9;

create view date_range as
    select curdate() - INTERVAL (a.n + (10 * b.n) + (100 * c.n)) DAY as date
    from zero_to_nine as a
    cross join zero_to_nine as b
    cross join zero_to_nine as c;

Vous pourrez alors faire une

select * from date_range

pour obtenir

date
---
2017-06-06
2017-06-05
2017-06-04
2017-06-03
2017-06-02
...
1
répondu Tom G 2017-06-06 12:48:54

c'est une bonne idée de générer ces dates à la volée. Cependant, je ne me sens pas à l'aise pour faire cela avec une gamme assez large donc j'ai fini avec la solution suivante:

  1. a créé une table" Datesnumber "qui conservera les nombres utilisés pour le calcul des dates:

CREATE TABLE DatesNumbers ( i MEDIUMINT NOT NULL, PRIMARY KEY (i) ) COMMENT='Used by Dates view' ;

  1. peuplé le tableau en utilisant les techniques ci-dessus avec des nombres de -59999 à 40000. Cette gamme me donnera des dates de 59999 jours (~164 ans) en retard à 40000 jours (109 ans) en avance:

INSERT INTO DatesNumbers SELECT a.i + (10 * b.i) + (100 * c.i) + (1000 * d.i) + (10000 * e.i) - 59999 AS i FROM (SELECT 0 AS i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS a , (SELECT 0 AS i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS b , (SELECT 0 AS i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS c , (SELECT 0 AS i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS d , (SELECT 0 AS i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS e ;

  1. a créé une vue" Dates":

SELECT i , CURRENT_DATE() + INTERVAL i DAY AS Date FROM DatesNumbers

C'est ça.

  • ( + ) requêtes faciles à lire
  • (+) Pas à la volée les numéros de générations
  • ( + ) donne des dates dans le passé et dans le futur et il n'y a pas D'UNION en vue pour cela comme dans ce post .
  • ( + )" dans le passé seulement "ou" dans le futur seulement "les dates peuvent être filtrées en utilisant WHERE i < 0 ou WHERE i > 0 (PK)
  • ( - ) "temporaire" de la table & de la vue est utilisé
1
répondu fifonik 2017-08-30 04:48:32

D'accord.. Essayez ceci: http://www.devshed.com/c/a/MySQL/Delving-Deeper-into-MySQL-50/

http://dev.mysql.com/doc/refman/5.0/en/loop-statement.html

http://www.roseindia.net/sql/mysql-example/mysql-loop.shtml

utilisez-le pour, disons, générer une table temp, puis faites un select * sur la table temp. Ou produisez les résultats un à la fois.

ce que vous dites que vous voulez faire ne peut pas être fait avec une déclaration SELECT , mais il pourrait être faisable avec des choses spécifiques à MySQL.

Encore une fois, peut-être que vous avez besoin de curseurs: http://dev.mysql.com/doc/refman/5.0/en/cursors.html

0
répondu Trevoke 2010-01-28 19:38:31

pour Oracle, ma solution est:

select trunc(sysdate-dayincrement, 'DD') 
  from dual, (select level as dayincrement 
                from dual connect by level <= 30)

Sysdate peut être modifié en date spécifique et le numéro de niveau peut être modifié pour donner plus de dates.

0
répondu mousetwentytwo 2013-10-29 16:57:29

si vous voulez la liste des dates entre deux dates:

create table #dates ([date] smalldatetime)
while @since < @to
begin
     insert into #dates(dateadd(day,1,@since))
     set @since = dateadd(day,1,@since)
end
select [date] from #dates

* fiddle here: http://sqlfiddle.com/#!6 / 9eecb / 3469

0
répondu celerno 2015-04-08 17:57:26
set language  'SPANISH'
DECLARE @table table(fechaDesde datetime , fechaHasta datetime ) 
INSERT @table VALUES('20151231' , '20161231');
WITH x AS 
    (
        SELECT   DATEADD( m , 1 ,fechaDesde ) as fecha  FROM @table
        UNION ALL
        SELECT  DATEADD( m , 1 ,fecha )
        FROM @table t INNER JOIN x ON  DATEADD( m , 1 ,x.fecha ) <= t.fechaHasta
    )
SELECT LEFT( CONVERT( VARCHAR, fecha , 112 ) , 6 ) as Periodo_Id 
,DATEPART ( dd, DATEADD(dd,-(DAY(fecha)-1),fecha)) Num_Dia_Inicio
,DATEADD(dd,-(DAY(fecha)-1),fecha) Fecha_Inicio
,DATEPART ( mm , fecha ) Mes_Id
,DATEPART ( yy , fecha ) Anio
,DATEPART ( dd, DATEADD(dd,-(DAY(DATEADD(mm,1,fecha))),DATEADD(mm,1,fecha))) Num_Dia_Fin
,DATEADD(dd,-(DAY(DATEADD(mm,1,fecha))),DATEADD(mm,1,fecha)) ultimoDia
,datename(MONTH, fecha) mes
,'Q' + convert(varchar(10),  DATEPART(QUARTER, fecha)) Trimestre_Name
FROM x 
OPTION(MAXRECURSION 0)
0
répondu Benigno Geronimo 2015-12-02 16:00:05
DELIMITER $$
CREATE PROCEDURE GenerateRangeDates(IN dateStart DATE, IN dateEnd DATE)
BEGIN

    CREATE TEMPORARY TABLE IF NOT EXISTS dates (day DATE);

    loopDate: LOOP
        INSERT INTO dates(day) VALUES (dateStart); 
        SET dateStart = DATE_ADD(dateStart, INTERVAL 1 DAY);

        IF dateStart <= dateEnd 
            THEN ITERATE loopDate;
            ELSE LEAVE loopDate;
        END IF;
    END LOOP loopDate;

    SELECT day FROM dates;
    DROP TEMPORARY TABLE IF EXISTS dates;

END 
$$

-- Call procedure
call GenerateRangeDates( 
        now() - INTERVAL 40 DAY,
        now()
    );
0
répondu Victor Silva 2016-04-23 00:05:16

SQLite version de RedFilters top solution

select d.Date
from (
    select 
    date(julianday('2010-01-20') + (a.a + (10 * b.a) + (100 * c.a))) as Date
    from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) d
where 
d.Date between '2010-01-20' and '2010-01-24' 
order by d.Date
0
répondu martin 2016-06-20 09:52:25

amélioré avec un jour de semaine un joindre une table de vacances personnalisée microsoft MSSQL 2012 pour powerpivot date table https://gist.github.com/josy1024/cb1487d66d9e0ccbd420bc4a23b6e90e

with [dates] as (
    select convert(datetime, '2016-01-01') as [date] --start
    union all
    select dateadd(day, 1, [date])
    from [dates]
    where [date] < '2018-01-01' --end
)
select [date]
, DATEPART (dw,[date]) as Wochentag
, (select holidayname from holidaytable 
where holidaytable.hdate = [date]) 
as Feiertag
from [dates]
where [date] between '2016-01-01' and '2016-31-12'
option (maxrecursion 0)
0
répondu josy1024 2016-07-14 16:39:10