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
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.
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;
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)
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.
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
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.
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#
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.
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
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') ;
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;
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
);
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
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')
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
...
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:
- 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'
;
- 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
;
- 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
ouWHERE i > 0
(PK) - ( - ) "temporaire" de la table & de la vue est utilisé
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
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.
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
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)
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()
);
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
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)