generowanie dni od zakresu dat

Chciałbym uruchomić zapytanie typu

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

I zwraca dane typu:

days
----------
2010-01-20
2010-01-21
2010-01-22
2010-01-23
2010-01-24
Author: Pentium10, 2010-01-28

23 answers

To rozwiązanie wykorzystuje żadnych pętli, procedur ani tabel temp . Subquery generuje daty dla ostatnich tysięcy dni i może być przedłużony, aby przejść tak daleko do tyłu lub do przodu, jak chcesz.

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' 

Wyjście:

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

Uwagi dotyczące wykonania

Testowanie go tutaj wydajność jest zaskakująco dobra: powyższe zapytanie zajmuje 0.0009 sek.

Jeśli rozszerzymy subquery, aby wygenerować ok. 100 000 numerów (a więc ok. 274 lat dat), trwa w 0.0458 sek.

Nawiasem mówiąc, jest to bardzo przenośna technika, która działa z większością baz danych z niewielkimi zmianami.

Przykład SQL zwracający 1000 dni

 284
Author: RedFilter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-30 17:07:55

Oto kolejna odmiana wykorzystująca widoki:

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;

I wtedy można po prostu zrobić(zobacz, jak elegancki jest?):

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

Update

Warto zauważyć, że będziesz mógł wygenerować tylko poprzednie daty począwszy od bieżącej daty . Jeśli chcesz wygenerować dowolny zakres dat (przeszłość, przyszłość i pomiędzy), musisz użyć tego widoku:

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
Author: Stéphane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-22 21:08:29

Zaakceptowana odpowiedź nie działa dla PostgreSQL (błąd składni Przy lub w pobliżu "a").

Sposób w jaki robisz to w PostgreSQL jest za pomocą generate_series funkcja, tzn.:

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
Author: Dmitry Gusev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-05 12:21:11

Używając rekurencyjnego wyrażenia Common Table (CTE), możesz wygenerować listę dat, a następnie wybrać z niej. Oczywiście normalnie nie chcesz utworzyć trzy miliony dat, więc to tylko ilustruje możliwości. Można po prostu ograniczyć zakres dat wewnątrz CTE i pominąć klauzulę where z instrukcji select przy użyciu 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)

Na Microsoft SQL Server 2005 wygenerowanie listy CTE wszystkich możliwych dat zajęło 1:08. Generowanie sto lat zajęło mniej niż drugi.

 12
Author: Joshua,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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

Wyjście

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
Author: SUHAIL AG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-28 08:41:15

Starym rozwiązaniem do robienia tego bez pętli / kursora jest utworzenie tabeli NUMBERS, która ma pojedynczą kolumnę całkowitą o wartościach zaczynających się od 1.

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

Musisz wypełnić tabelę wystarczającą ilością rekordów, aby pokryć swoje potrzeby:

INSERT INTO NUMBERS (id) VALUES (NULL);

Gdy masz NUMBERS tabelę, możesz użyć:

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'

Absolutnym rozwiązaniem low-tech byłoby:

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

Do czego byś go użył?


Aby wygenerować listy dat lub liczb w celu pozostawienia Dołącz na za. Możesz to zrobić, aby zobaczyć, gdzie są luki w danych, ponieważ pozostajesz dołączając do listy sekwencyjnych danych - wartości null sprawią, że oczywiste będzie, gdzie istnieją luki.

 4
Author: OMG Ponies,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-28 19:51:00

Dla Access 2010 - wymagane jest wiele kroków; postępowałem zgodnie z tym samym wzorem, co napisano powyżej, ale pomyślałem, że mogę komuś pomóc w Access. Świetnie mi się sprawdziło, nie musiałem trzymać tabeli z datami.

Tworzenie tabeli o nazwie DUAL (podobnie jak w przypadku Oracle DUAL table)
  • ID (AutoNumber)
  • DummyColumn (Tekst)
  • Dodaj wartości jednego wiersza (1,"DummyRow")

Utwórz Zapytanie o nazwie "ZeroThru9Q"; ręcznie wprowadź następujące składnia:

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;

Utwórz Zapytanie o nazwie "TodayMinus1KQ" (dla dat sprzed dzisiaj); ręcznie wprowadź następującą składnię:

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

Utwórz Zapytanie o nazwie "TodayPlus1KQ" (dla dat po dniu dzisiejszym); ręcznie wprowadź następującą składnię:

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;

Utwórz Zapytanie o nazwie "TodayPlusMinus1KQ" (dla dat +/- 1000 dni):

SELECT MyDate
FROM TodayMinus1KQ
UNION
SELECT MyDate
FROM TodayPlus1KQ;

Teraz możesz użyć zapytania:

SELECT MyDate
FROM TodayPlusMinus1KQ
WHERE MyDate BETWEEN #05/01/2014# and #05/30/2014#
 4
Author: Travis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-25 19:27:24

Thx Pentium10 - you made me join stackoverflow :) - to jest mój Port do msaccess-myślę, że zadziała na każdej wersji:

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

Odwołuje się do MSysObjects tylko dlatego, że access potrzebuje tabeli liczącej co najmniej 1 rekord, w klauzuli from - wystarczy każda tabela z co najmniej 1 rekordem.

 3
Author: user3780177,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-26 17:05:22

Procedura + tabela tymczasowa:

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
Author: Márcio Souza Júnior,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-12 15:32:16

Spróbuj tego.

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
Author: loalexzzzz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-28 09:16:45

Jeśli będziesz potrzebował więcej niż kilka dni, potrzebujesz stolika.

Tworzenie zakresu dat w mysql

Wtedy,

select from days.day, count(mytable.field) as fields from days left join mytable on day=date where date between x and y;
 1
Author: gcb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:24

Jak stwierdzono (lub przynajmniej nawiązano do) w wielu wspaniałych odpowiedziach już udzielonych, problem ten można łatwo rozwiązać, gdy masz zestaw liczb do pracy.

Uwaga: Poniżej znajduje się T-SQL, ale jest to po prostu moja szczególna implementacja ogólnych pojęć już wymienionych tutaj i w Internecie w ogóle. Konwersja kodu na wybrany dialekt powinna być stosunkowo prosta.

Jak? rozważ to zapytanie:

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

Powyższe daje zakres dat 1/22/0001 - 1/27/0001 i jest niezwykle trywialny. W powyższym zapytaniu znajdują się 2 Kluczowe Informacje: Data rozpoczęcia z 0001-01-22 i offset z 5. Jeśli połączymy te dwie informacje, to oczywiście mamy naszą datę zakończenia. Tak więc, biorąc pod uwagę dwie daty, generowanie zakresu można podzielić tak:

  • Znajdź różnicę między dwoma podanymi datami (offset), łatwo:

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

    Używając ABS() tutaj zapewnia, że kolejność dat jest nieistotna.

  • Wygeneruj Ograniczony zbiór liczb, również łatwy:

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

    Zauważ, że nie obchodzi nas, co wybieramy FROM tutaj. Potrzebujemy tylko zestawu do pracy, aby policzyć liczbę wierszy w nim. Ja osobiście używam TVF, niektórzy używają CTE, inni zamiast tego używają tabeli liczb, rozumiesz. Opowiadam się za użyciem najbardziej wydajnego rozwiązania, które również rozumiesz.

łączenie te dwie metody rozwiążą nasz problem:

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

Powyższy przykład jest okropnym kodem, ale pokazuje, jak wszystko się łączy.

Więcej Zabawy

Muszę robić tego typu rzeczy często, więc zamknąłem logikę w dwóch telewizorach. Pierwszy generuje zakres liczb, a drugi wykorzystuje tę funkcję do generowania zakresu dat. Matematyka ma zapewnić, że kolejność wprowadzania nie ma znaczenia i dlatego, że chciałem użyć pełnego zakresu liczb dostępne w GenerateRangeSmallInt.

Następująca funkcja zajmuje ~16ms czasu procesora, aby zwrócić maksymalny zakres 65536 dat.

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
Author: Kittoes0124,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-25 14:25:06

Generowanie dat pomiędzy dwoma polami daty

Jeśli jesteś świadomy z zapytaniem SQL CTE, to To rozwiązanie pomoże Ci rozwiązać twoje pytanie

Oto przykład

Mamy daty w jednej tabeli

Nazwa tabeli: "testdate"

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

Wymagaj Wyniku:

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

Rozwiązanie:

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

Explanation: CTE Recursive query explanation

  • pierwsza część zapytanie:

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

    Explanation: firstcolumn to "startdate", Druga kolumna to różnica początku i końca date in days and it will be considered as "diff" column

  • druga część zapytania:

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

    Explanation: Union all dziedziczy wynik powyższego zapytania, dopóki wynik nie osiągnie wartości null, Tak więc wynik" StartTime " jest dziedziczony z wygenerowanego zapytania CTE, a z diff, decreate - 1, więc wygląda na 3, 2 i 1 dopóki 0

Na przykład

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

Specyfikacja Wyniku

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. Część zapytania

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

    Doda dzień "diff" w "startdate", więc wynik powinien być jak poniżej

Wynik

STARTDATE
10/24/2012
10/27/2012
10/28/2012
10/29/2012
10/30/2012
 1
Author: Tarun Harkinia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-25 19:27:45

Krótsza od zaakceptowanej odpowiedzi, ten sam pomysł:

(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
Author: daniherculano,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-21 09:23:39

Dla każdego, kto chce to zapisać jako widok (MySQL nie obsługuje zagnieżdżonych poleceń select w widokach):

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;

Możesz wtedy zrobić

select * from date_range

Aby uzyskać

date
---
2017-06-06
2017-06-05
2017-06-04
2017-06-03
2017-06-02
...
 1
Author: Tom G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-06 12:48:54

To dobry pomysł z generowaniem tych dat w locie. Jednak nie czuję się komfortowo, aby to zrobić z dość dużym zasięgiem, więc skończyłem z następującym rozwiązaniem: {]}

  1. Utworzono tabelę "DatesNumbers", która będzie zawierać liczby używane do obliczania dat:

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

  1. wypełniono tabelę przy użyciu powyższych technik liczbami od -59999 do 40000. Ten zakres da mi daty od 59999 dni (~164 lat) do 40000 dni (109 lat) przed:

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. Utworzono widok "daty":

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

To wszystko.
  • ( + ) łatwe do odczytania zapytania
  • (+) No On The fly numbers
  • (+) podaje daty w przeszłości i w przyszłości i nie ma związku na to jak w ten post .
  • (+) "tylko w przeszłości" lub "tylko w przyszłości" daty mogą być filtrowane za pomocą WHERE i < 0 lub WHERE i > 0 (PK)
  • ( -) używana jest 'tymczasowa' tabela i widok
 1
Author: fifonik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-30 04:48:32

W porządku.. Spróbuj tego.: 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{[2]

Użyj tego, aby, powiedzmy, wygenerować tabelę tymczasową, a następnie wykonać select * na tabeli tymczasowej. Lub wyświetlać wyniki pojedynczo.
to, co mówisz, że chcesz zrobić, nie może być wykonane za pomocą instrukcji SELECT , ale może być wykonalne z rzeczami specyficzne dla MySQL.
Ale może potrzebujesz kursorów: http://dev.mysql.com/doc/refman/5.0/en/cursors.html

 0
Author: Trevoke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-28 19:38:31

Dla Oracle moje rozwiązanie to:

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

Sysdate można zmienić na konkretną datę i numer poziomu można zmienić, aby podać więcej dat.

 0
Author: mousetwentytwo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-29 16:57:29

Jeśli chcesz listę dat pomiędzy dwoma datami:

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
Author: celerno,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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
Author: Benigno Geronimo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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
Author: Victor Silva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-23 00:05:16

SQLite wersja 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
Author: martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-20 09:52:25

Poprawiono z dniem powszednim i dołączeniem niestandardowego stołu świątecznego microsoft MSSQL 2012 Dla powerpivot data 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
Author: josy1024,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-14 16:39:10