복붙노트

[SQL] 어떻게 MySQL의 데이터를 생성하는?

SQL

어떻게 MySQL의 데이터를 생성하는?

여기 내 SQL은 다음과 같습니다

SELECT 
  COUNT(id),
  CONCAT(YEAR(created_at), '-', MONTH(created_at), '-', DAY(created_at))
FROM my_table
GROUP BY YEAR(created_at), MONTH(created_at), DAY(created_at)

나는 행이도 생성되지 않음 ID가 없었다 일 동안 표시하고 싶습니다. 지금은 활동이 없었다 일 날짜의 톤을 누락.

이 쿼리를 변경하는 방법에 대한 생각은 그렇게합니까?

해결법

  1. ==============================

    1.방법은 하나 개의 쿼리에서 그것을 할 수 있습니다 :

    방법은 하나 개의 쿼리에서 그것을 할 수 있습니다 :

    SELECT COUNT(my_table.id) AS total,
     CONCAT(YEAR(dates.ddate), '-', MONTH(dates.ddate),  '-', DAY(dates.ddate))
    FROM (
       -- Creates "on the fly" 65536 days beginning from 2000-01-01 (179 years)
       SELECT DATE_ADD("2000-01-01", INTERVAL (b1.b + b2.b + b3.b + b4.b + b5.b + b6.b + b7.b + b8.b + b9.b + b10.b + b11.b + b12.b + b13.b + b14.b + b15.b + b16.b) DAY) AS ddate FROM
       (SELECT 0 AS b UNION SELECT 1) b1,
       (SELECT 0 AS b UNION SELECT 2) b2,
       (SELECT 0 AS b UNION SELECT 4) b3,
       (SELECT 0 AS b UNION SELECT 8) b4,
       (SELECT 0 AS b UNION SELECT 16) b5,
       (SELECT 0 AS b UNION SELECT 32) b6,
       (SELECT 0 AS b UNION SELECT 64) b7,
       (SELECT 0 AS b UNION SELECT 128) b8,
       (SELECT 0 AS b UNION SELECT 256) b9,
       (SELECT 0 AS b UNION SELECT 512) b10,
       (SELECT 0 AS b UNION SELECT 1024) b11,
       (SELECT 0 AS b UNION SELECT 2048) b12,
       (SELECT 0 AS b UNION SELECT 4096) b13,
       (SELECT 0 AS b UNION SELECT 8192) b14,
       (SELECT 0 AS b UNION SELECT 16384) b15,
       (SELECT 0 AS b UNION SELECT 32768) b16
     ) dates
     LEFT JOIN my_table ON dates.ddate = my_table.created_at
     GROUP BY dates.ddate
     ORDER BY dates.ddate
    

    당신이 검사 할 "MY_TABLE"는 질문에 표시가없는 경우 다음 코드는 필요하다 :

    create table `my_table` (
        `id` int (11),
        `created_at` date 
    ); 
    insert into `my_table` (`id`, `created_at`) values('1','2000-01-01');
    insert into `my_table` (`id`, `created_at`) values('2','2000-01-01');
    insert into `my_table` (`id`, `created_at`) values('3','2000-01-01');
    insert into `my_table` (`id`, `created_at`) values('4','2001-01-01');
    insert into `my_table` (`id`, `created_at`) values('5','2100-06-06');
    
  2. ==============================

    2.SQL은 데이터베이스에없는 데이터를 반환에서 악명 나쁘다. 당신은 날짜의 간격의 시작과 끝 값을 찾을 수 있지만, 모든 날짜를 얻는 것은 어렵다 수 있습니다.

    SQL은 데이터베이스에없는 데이터를 반환에서 악명 나쁘다. 당신은 날짜의 간격의 시작과 끝 값을 찾을 수 있지만, 모든 날짜를 얻는 것은 어렵다 수 있습니다.

    이 솔루션은 각 날짜에 대해 하나 개의 레코드와 함께 일정 테이블을 작성하고 OUTER는 쿼리에 가입하세요.

    여기 created_at이 유형 DATE라고 가정하는 예이다 :

    SELECT calendar_date, COUNT(`id`)
    FROM calendar LEFT OUTER JOIN my_table ON calendar.calendar_date = my_table.created_at
    GROUP BY calendar_date
    

    (당신은 테이블을 조인하기 위해 조금 더 많은 체조를해야 할 것이다, 그래서 나는 정말 DATETIME을 그 created_at을 추측하고있어).

  3. ==============================

    3.일반적인 생각

    일반적인 생각

    MySQL의 데이터를 생성하는 두 가지 방법이 있습니다. 쿼리를 실행하고 다른 하나는 데이터베이스에 그것을 가지고하는 것입니다 필요한 경우를 사용할 때 하나는 즉석에서 데이터를 생성하는 것입니다. 당신이 자주 쿼리를 실행하는 거라면 물론, 두 번째는 첫 번째보다 더 빨리 될 것입니다. 그러나, 두 번째는 유일한 목적이 누락 된 데이터를 생성하는 것입니다 데이터베이스의 테이블이 필요합니다. 또한 해당 테이블을 만들 충분한 권한을 가지고 당신이 필요합니다.

    동적 데이터 생성

    이 방법은 함께 실제 테이블을 조인하는 데 사용할 수있는 가짜 테이블을 생성하는 조합을 포함한다. 두려운 반복적 인 쿼리는 다음과 같습니다

    select aDate from (
      select @maxDate - interval (a.a+(10*b.a)+(100*c.a)+(1000*d.a)) day aDate 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) a, /*10 day range*/
      (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) b, /*100 day range*/
      (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) c, /*1000 day range*/
      (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) d, /*10000 day range*/
      (select @minDate := '2001-01-01', @maxDate := '2002-02-02') e
    ) f
    where aDate between @minDate and @maxDate
    

    어쨌든, 것보다 간단합니다. 결과는 X 쿼리에 파생 테이블의 양을 10 ^ X 행 것이다 그래서 10 개 수치 도출 테이블 직교 제품을 만든다. 당신이 이상 이십칠년의 기간을 대표 할 수있을 것이다, 그래서이 예에서 만일의 범위가있다. 당신이 더 필요한 경우, 쿼리에 다른 UNION을 추가하고 간격을 업데이트하고, 당신이 필요하지 않은 경우에는 파생 테이블에서 노동 조합 또는 개별 값을 제거 할 수있는 많은 있도록. 그냥 명확히하기 위해, 당신은 @minDate 및 @maxDate 변수에 WHERE 절을 사용하여 필터를 적용하여 조정할 날짜 기간을 세밀하게 할 수 있습니다 (하지만 당신은 직교 제품을 만든 것보다 더 긴 기간을 사용하지 않음).

    정적 데이터 생성

    이 솔루션은 데이터베이스에서 테이블을 생성 할 필요합니다. 접근 방식은 이전과 비슷합니다. X가 최대 필요한 범위이고 1에서 X까지 정수의 범위 : 당신은 그 테이블에 먼저 데이터를 삽입해야합니다. 확실에게 단지 삽입 100000 개 값을하고 있다면 다시 말하지만, 당신은 273 년 이상 일의 범위를 만들 수 있습니다. 당신은 정수의 순서를 가지고 그래서 일단,이 같은 날짜 범위로 변환 할 수 있습니다 :

    select '2012-01-01' + interval value - 1 day aDay from seq
    having aDay <= '2012-01-05'
    

    열 이름 값을 가진 테이블라는 이름의 서열을 가정. 일로부터 현재까지 바닥 상기 상단에.

    뭔가 유용한로이 켜기

    자, 이제 우리는 우리의 날짜 기간이 발생하지만, 우리는 여전히 쿼리 데이터에 방법을 누락 왼쪽 구조에 관해서 가입 이것은 실제 0으로 누락 된 값을 표시하고 있습니다. 우리가 같은 페이지에 모두있어, 왼쪽 조인 내부 조인과 유사하지만 한 가지 차이점 확인하십시오 : 조인의가에 관계없이에 일치하는 레코드가 있는지의 왼쪽 테이블에서 모든 기록을 보존한다 우측의 테이블. 왼쪽 오른쪽 테이블에 일치하는 기록이없는 왼쪽의 기록을 위해, 왼쪽 테이블에 사람을 유지할 것 가입하면서 가입에 즉, 내부 조인, 왼쪽이 아닌 모든 일치하는 행을 제거합니다 가입 널 값이 "공간"을 채울 것입니다.

    우리는 우리의 새로 생성 된 테이블은 모든 요소에 관계없이 자신의 존재를 고려되도록, 조인의 왼쪽 부분과 오른쪽에 이전에 후자를 넣어 우리의 도메인 테이블 (데이터 "실종"한 하나)에 가입해야합니다 그래서 도메인 테이블입니다.

    예를 들어, 우리가 필드의 ID와 테이블 domainTable했다, 생년월일 그리고 우리는이 쿼리 수, 그 값을 보여주기 위해 하루에 0 카운트의 경우 2012 년 처음 5 일 내에 생년월일 모든 수를보고 싶다 실행 :

    select allDays.aDay, count(dt.id) from (
      select '2012-01-01' + interval value - 1 day aDay from seq
      having aDay <= '2012-01-05'
    ) allDays
    left join domainTable dt on allDays.aDay = dt.birthDate
    group by allDays.aDay
    

    모든 요일이 표시 될 수 있도록이 상관없이 우리 도메인 테이블에 일치하는 값이 있는지 여부, 좌측 우리 도메인 테이블에 대해 조인 파생 모든 requried 일 테이블 (통지 I 정적 데이터 생성 사용하고) 및 수행을 생성 . 또한 카운트 사람들은 계산되지 않습니다으로 널 (null) 값을 가질 것이다 분야에서 수행해야합니다 유의하십시오.

    주의 사항이 고려되어야합니다

    1) 쿼리는 코드에 작은 변화를 수행하는) 다른 간격 (월, 년을 조회 할 수 있습니다

    2) 대신 날짜를 하드 코딩이 같은 도메인 테이블에서 최소 및 최대 값을 조회 할 수 있습니다 :

    select (select min(aDate) from domainTable) + interval value - 1 day aDay
    from seq
    having aDay <= (select max(aDate) from domainTable)
    

    이는 필요 이상의 레코드가 발생하지 않도록한다.

    실제로 귀하의 질문에 대답

    나는 당신이 이미 당신이 원하는 일을하는 방법을 알아 낸한다고 생각합니다. 다른 사람들도 그 혜택을 누릴 수 있도록 어쨌든, 여기 단계입니다. 첫째, 정수 테이블을 만듭니다. 둘째,이 쿼리를 실행 :

    select allDays.aDay, count(mt.id) aCount from (
        select (select date(min(created_at)) from my_table) + interval value - 1 day aDay
        from seq s
        having aDay <= (select date(max(created_at)) from my_table)
    ) allDays
    left join my_table mt on allDays.aDay = date(mt.created_at)
    group by allDays.aDay
    

    나는 당신이 그 방법을 연결하는 이유 created_at는 날짜와 그의 것 같다. 난 그냥 날짜 필드에 의해 그룹화하지만 실제 날짜 데이터 형식에 created_at을 주조하고있어 그래서 그러나,이 방식 MySQL은 기본적으로 저장 날짜로 발생합니다. 당신은이 바이올린을 사용하여 재생할 수 있습니다.

    여기서 동적으로 생성 용액 데이터이다 :

    select allDays.aDay, count(mt.id) aCount from (
      select @maxDate - interval a.a day aDay 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) a, /*10 day range*/
      (select @minDate := (select date(min(created_at)) from my_table),
              @maxDate := (select date(max(created_at)) from my_table)) e
       where @maxDate - interval a.a day between @minDate and @maxDate
    ) allDays
    left join my_table mt on allDays.aDay = date(mt.created_at)
    group by allDays.aDay
    

    쿼리의 골격을 볼 수있는 것은 이전과 동일합니다. 변경 유일하게 파생 테이블 allDays가 생성되는 방법이다. 이제, 파생 테이블이 생성되는 방식도 내가 전에 추가 한 것과 약간 다릅니다. 예제 filddle에 난 단지 10 일의 범위를 필요로하기 때문이다. 당신이 볼 수 있듯이, 그것은 천일 범위를 추가하는 것보다 더 읽을 수 있습니다. 당신이 너무 그것으로 재생할 수 있도록 여기에 동적 솔루션의 바이올린입니다.

    도움이 되었기를 바랍니다!

  4. ==============================

    4.테스트 베드 :

    테스트 베드 :

    create table testbed (id integer, created_at date);
    insert into testbed values
           (1, '2012-04-01'),
           (1, '2012-04-30'),
           (2, '2012-04-02'),
           (3, '2012-04-03'),
           (3, '2012-04-04'),
           (4, '2012-04-04');
    

    나는 또한이 같은 인위적으로 만든, any_table 사용

    create table any_table (id integer);
    insert into any_table values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
    insert into any_table select * from any_table; -- repeat this insert 7-8 times
    

    일년에 충당하기 위해, 분 (created_dt) 범위 적어도 365 - 그런 다음 최대 (created_dt) 이상의 행이 예상되는 데이터베이스의 모든 테이블을 사용할 수 있습니다.

    질문:

    SELECT concat(year(dr._date),'-',month(dr._date),'-',day(dr._date)),
           -- or, instead of concat(), simply: dr._date
           count(id)
      FROM (
            SELECT date_add(r.mindt, INTERVAL @dist day) _date,
                   @dist := @dist + 1 AS days_away
              FROM any_table t
              JOIN (SELECT min(created_at) mindt,
                           max(created_at) maxdt,
                           @dist := 0
                      FROM testbed) r
             WHERE date_add(r.mindt, INTERVAL @dist day) <= r.maxdt) dr
      LEFT JOIN testbed tb ON dr._date = tb.created_at
     GROUP BY dr._date;
    
  5. from https://stackoverflow.com/questions/10034668/how-to-generate-data-in-mysql by cc-by-sa and MIT license