2012-06-26 5 views
0

잠시 동안이 항목을 정렬하려고했습니다. 나는 정말 어떤 도움을 주셔서 감사합니다.mysql이 특정 달을 건너 뜁니다.

날짜와 int 값이 각각 2 열인이 테이블이 있습니다. 문제는 mysql이 int 값이 null 인 모든 날짜 값을 건너 뛴다는 것입니다.

여기에 SQL 문을

SELECT DATE_FORMAT(sales_date_sold, '%b \'%y') 
    AS sale_date, sales_amount_sold 
    AS sale_amt 
    FROM yearly_sales 
    WHERE sales_date_sold BETWEEN DATE_SUB(SYSDATE(), INTERVAL 2 YEAR) AND SYSDATE() 
    GROUP BY YEAR(sales_date_sold), MONTH(sales_date_sold) 
    ORDER BY YEAR(sales_date_sold), MONTH(sales_date_sold) ASC; 

몇 사람과 함께 그래서 그 달이 생략됩니다 2011년 2월에 대한 값은이 없습니다. Coalesce 및 if_null도 작동하지 않습니다.

+0

(가독성을 위해 쿼리 텍스트의 형식을 변경하여 서식을 다시 지정) – spencer7593

답변

1

차원의 모든 달에 대한 값을 제공하는 행 소스가 필요하며 yearly_sales 테이블을 왼쪽으로 조인하면됩니다.

GROUP BY를 수행 중이며 측정 값 (sales_amount_sold)에 집계가 있거나 GROUP BY를 원하지 않을 가능성이 큽니다. (귀하의 질문에 쿼리 그건 당신이 원하는 것을 할 수있다. 주어진 달에 하나의 행에 대해 sales_amount_sold에서 값을 반환하는 것입니다,하지만 매우 이상한 결과 집합을 반환 할 수 있습니다.)


한 가지 방법이다 "calendar_month"테이블에 반환하고자하는 모든 달의 DATE 값을 포함해야합니다.

SELECT m.month       AS sale_date 
    , IFNULL(SUM(s.sales_amount_sold),0) AS sale_amt 
    FROM calendar_months m 
    LEFT 
    JOIN yearly_sales s 
    ON s.sales_date_sold >= m.month 
    AND s.sales_date_sold < DATE_ADD(m.month,INTERVAL 1 MONTH) 
WHERE m.month BETWEEN DATE_SUB(SYSDATE(), INTERVAL 2 YEAR) AND SYSDATE() 
GROUP BY m.month 
ORDER BY m.month 

이 쿼리는 약간 다른 결과를 반환합니다 (이 생성하는 다른 방법, 다른 곳에서 유래에 대한 질문에 대한 기존의 답변이 있습니다), 당신은 단지 "전체 개월 '의 그룹 행을 얻을 것보다는 포함된다 sales_date의 WHERE 절이 2 년 전에 "첫 번째 달"이 아닌 현재 날짜와 시간보다 2 년 앞선 것을 참조하기 때문에 원래 쿼리에서와 같이 부분적인 월을 사용합니다.

calendar_months 테이블은 반드시 필요하지 않습니다. 이것은 행 원본을 반환하는 쿼리로 대체 될 수 있습니다. 이 경우 월 값의 술어를 외부 쿼리에서 하위 쿼리로 이동할 수 있습니다.


부록 : 당신이 행 원본으로 calendar_month 테이블을 사용하는 경우, 당신은 반환 할 모든 가능한 "달"값으로 채 웁니다해야합니다.

CREATE TABLE calendar_month 
(`month` DATE NOT NULL PRIMARY KEY COMMENT 'one row for first day of each month'); 

INSERT INTO calendar_month(`month`) VALUES ('2011-01-01'),('2011-02-01'),('2011-03-01') 
대안으로

, 당신은 인라인보기보다는 테이블 참조로, 동적으로 생성 된 행 원본을 지정할 수 있습니다. (비슷한 쿼리를 사용하여 calendar_months 테이블을 빠르게 채울 수 있습니다.)

이 쿼리를 괄호로 묶은 다음 이전 쿼리에서 FROMcalendar_months 사이에 붙여 넣을 수 있습니다.

SELECT DATE_ADD('1990-01-01',INTERVAL 1000*thousands.digit + 100*hundreds.digit + 10*tens.digit + ones.digit MONTH) AS `month` 
    FROM (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) ones 
    JOIN (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) tens 
    JOIN (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) hundreds 
    JOIN (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) thousands 
+0

빈 결과 집합을 얻었습니다. 당신이 calendar_months 행 소스를 "드라이버"로 만들고 싶다면, (매년 year_sales를 선택하십시오.) 왼쪽 join calender_months ... – goonerify

+0

매월 첫날에 calender_months를 채워야합니다. 그래서 LEFT JOIN의 왼쪽에 있어야합니다. – spencer7593

+0

달 값의 rowsource와 같이 동적으로 생성 된 인라인 뷰의 추가 된 예 – spencer7593

0

타임 스탬프가있는이 문제가 발생했습니다. 내가 사용한 솔루션은 모든 달에 참조 테이블을 만드는 것이 었습니다. 이것은 숫자가 1-12 (12 행) 인 테이블 일 수도 있고 한 걸음 더 나아가 월 이름을 넣을 수도 있습니다. 그런 다음 yearly_sales 테이블을 1_through_12 테이블에 가입 시키면 매월 얻을 수 있습니다.

1

문제는 값이 NULL이 아니라 데이터베이스에서 데이터를 선택한다는 것입니다. 특정 월의 데이터가 없다면, MySQL은 거기에없는 데이터를 선택할 방법이 없습니다.

MySQL을 완전히이 문제를 해결하는 유일한 방법은 왜 그냥 0 NULL 대신를 사용하지 않는 already answered in a very similar question

+1

+1에 대한 질문에 대한 참조를 게시했습니다. – spencer7593

0

입니까?

+0

네가 맞아, 스토어드 프로 시저와 이벤트가 null 값을 확인하고 0 값을 삽입하기 위해 데이터를 반복 할 수 있다고 생각한다. 그런 문제에 대한 과잉과 같아 보입니다. – goonerify

관련 문제