2014-01-12 3 views
0

예약 날짜가 12 개월이 넘었지만 예약이없는 달에는 Null 또는 0을 가져야합니다. 예약없이MySQL 쿼리 - 지난 12 개월 동안의 매월 기록 값을 반환합니다.

SELECT bs.date,CONCAT(MONTHNAME(bs.date),' ', YEAR(bs.date)) as 'Month',count(*) AS Bookings, CONCAT(us.firstName,' ', us.lastName) as 'Name' from bookings bs RIGHT JOIN users us ON bs.clientID = us.recNo 
     WHERE bs.managerID = 6 AND bs.clientID = 1900 
     AND date > DATE_SUB(CURDATE(), INTERVAL 11 MONTH) AND date <= CURDATE() GROUP BY YEAR(date), month(date) 

누구를 도울 수 있습니까?

답변

0

당신은 하드 코딩하여 작업을 수행 할 수 있습니다 12 개월이 지난 후 users으로 CROSS JOIN을 누른 다음 bookings으로 LEFT JOIN (LEFT JOIN이 RIGHT JOIN보다 빠르다고 언급 한 적이 있습니다.) 우리가 원하는 결과를 필터링 관리자 ID와 클라이언트 ID를 확인하기 위해 WHERE 조건을 가지고 있지만 우리는 또한 널 (null)이 그것의 의미가 행을 반환 할 이유는 그래서 (sqlFiddle)
주에서 볼

SELECT bs.date, 
     CONCAT(MONTHNAME(hardcoded.date),' ', YEAR(hardcoded.date)) as 'Month', 
     count(bs.date) AS Bookings, 
     CONCAT(us.firstName,' ', us.lastName) as 'Name' 
from 
(SELECT CURDATE() as date UNION 
SELECT CURDATE()-INTERVAL 1 MONTH UNION 
SELECT CURDATE()-INTERVAL 2 MONTH UNION 
SELECT CURDATE()-INTERVAL 3 MONTH UNION 
SELECT CURDATE()-INTERVAL 4 MONTH UNION 
SELECT CURDATE()-INTERVAL 5 MONTH UNION 
SELECT CURDATE()-INTERVAL 6 MONTH UNION 
SELECT CURDATE()-INTERVAL 7 MONTH UNION 
SELECT CURDATE()-INTERVAL 8 MONTH UNION 
SELECT CURDATE()-INTERVAL 9 MONTH UNION 
SELECT CURDATE()-INTERVAL 10 MONTH UNION 
SELECT CURDATE()-INTERVAL 11 MONTH 
)as hardcoded 
CROSS JOIN users us 
LEFT JOIN bookings bs ON (MONTH(bs.date) = MONTH(hardcoded.date) 
         AND YEAR(bs.date) = YEAR(hardcoded.date)) 
         AND bs.clientID = us.recNo 
WHERE ((bs.managerID = 6 AND bs.clientID = 1900) 
     OR 
     (bs.managerID IS NULL AND bs.clientID IS NULL)) 
AND hardcoded.date > DATE_SUB(CURDATE(), INTERVAL 11 MONTH) AND hardcoded.date <= CURDATE() 
GROUP BY Month,Name 
ORDER BY hardcoded.date 

아래 쿼리 예약이없는 하드 코드 달. 그래서 이유가 있어요 OR (bs.managerID IS NULL AND bs.clientID IS NULL)
또한 현재 GROUP BY는 선택 항목 bs.date의 그룹을 지정하지 않으므로 비표준입니다. 한 달에 두 개 이상의 예약이있는 경우 현재 알 수없는 날짜를 반환합니다. 하나 이상한 것, 당신은 hardcoded.date 대신 GROUP BY를 선택하여 ANSI 표준의 적절한 GROUP BY를 가질 수 있습니다. 또는 MIN (bs.date) 또는 MAX (bs.date)에 MIN() 또는 MAX()와 같은 집계 함수를 사용하여 선택 항목의 첫 번째 필드에 항상 첫 번째 예약 날짜 또는 마지막 예약을 반환하는지 확인하십시오 해당 월에 2 개 이상의 예약이있는 경우 매월 날짜가 표시되므로 GROUP BY에 등록하지 않아도됩니다. 십자가 앱을 죽이거나되지 가입하면

는 모르겠지만이 하나 개가 CROSS없이 가입 것 하지만 보존 권리를 시도

SELECT bs.date, 
CONCAT(MONTHNAME(hardcoded.date),' ', YEAR(hardcoded.date)) as 'Month', 
count(bs.date) AS Bookings, 
CONCAT(us.firstName,' ', us.lastName) as 'Name' 
from 
(SELECT CURDATE() as date UNION 
SELECT CURDATE()-INTERVAL 1 MONTH UNION 
SELECT CURDATE()-INTERVAL 2 MONTH UNION 
SELECT CURDATE()-INTERVAL 3 MONTH UNION 
SELECT CURDATE()-INTERVAL 4 MONTH UNION 
SELECT CURDATE()-INTERVAL 5 MONTH UNION 
SELECT CURDATE()-INTERVAL 6 MONTH UNION 
SELECT CURDATE()-INTERVAL 7 MONTH UNION 
SELECT CURDATE()-INTERVAL 8 MONTH UNION 
SELECT CURDATE()-INTERVAL 9 MONTH UNION 
SELECT CURDATE()-INTERVAL 10 MONTH UNION 
SELECT CURDATE()-INTERVAL 11 MONTH 
)as hardcoded 
LEFT JOIN bookings bs ON (MONTH(bs.date) = MONTH(hardcoded.date) 
AND YEAR(bs.date) = YEAR(hardcoded.date)) 
RIGHT JOIN users us ON (bs.clientID = us.recNo OR bs.clientID IS NULL) 
WHERE ((bs.managerID = 6 AND bs.clientID = 1900) 
OR 
(bs.managerID IS NULL AND bs.clientID IS NULL)) 
AND hardcoded.date > DATE_SUB(CURDATE(), INTERVAL 11 MONTH) AND hardcoded.date <= CURDATE() 
GROUP BY Month,Name 
ORDER BY hardcoded.date 

합류하기 전에 기록을 좁힐 시도에 가입 할 수 있습니다

SELECT MIN(bs.date) as FirstBookingDate, 
CONCAT(MONTHNAME(hardcoded.date),' ', YEAR(hardcoded.date)) as 'Month', 
count(bs.date) AS Bookings, 
CONCAT(us.firstName,' ', us.lastName) as 'Name' 
from 
(SELECT CURDATE() as date UNION 
SELECT CURDATE()-INTERVAL 1 MONTH UNION 
SELECT CURDATE()-INTERVAL 2 MONTH UNION 
SELECT CURDATE()-INTERVAL 3 MONTH UNION 
SELECT CURDATE()-INTERVAL 4 MONTH UNION 
SELECT CURDATE()-INTERVAL 5 MONTH UNION 
SELECT CURDATE()-INTERVAL 6 MONTH UNION 
SELECT CURDATE()-INTERVAL 7 MONTH UNION 
SELECT CURDATE()-INTERVAL 8 MONTH UNION 
SELECT CURDATE()-INTERVAL 9 MONTH UNION 
SELECT CURDATE()-INTERVAL 10 MONTH UNION 
SELECT CURDATE()-INTERVAL 11 MONTH 
)as hardcoded 
CROSS JOIN (SELECT * FROM users WHERE recNo = 1900) us 
LEFT JOIN (SELECT * FROM bookings WHERE managerID = 6 AND clientID = 1900 
      AND date BETWEEN CURDATE()-INTERVAL 11 MONTH AND CURDATE()) bs 
ON (MONTH(bs.date) = MONTH(hardcoded.date) 
AND YEAR(bs.date) = YEAR(hardcoded.date)) 
GROUP BY Month,Name 
ORDER BY hardcoded.date 
+0

피들에서는 잘 작동하지만 쿼리는 phpmyadmin에서 아무 것도 반환하지 않습니다. 실제로는 수동으로 애플리케이션을 죽일 때까지 당황합니다. 어떤 생각? – Deepa

+0

사용자 테이블의 크기는 얼마입니까? –

+0

CROSS JOIN이 사용자 테이블의 크기에 따라 사용자를 죽이게하는지 알 수 없습니다. 하지만 방금 교차 쿼리없이 아래쪽에있는 다른 쿼리로 내 대답을 업데이트했습니다. (오른쪽 조인 유지) –

0

저는 MySQL 구문에 익숙하지 않지만, 먼저 월 및 연도 정수 열만있는 임시 테이블을 만들고 지난 해 매월 레코드를 삽입하여 접근합니다. DATESUB와 감소 카운터를 사용하는 간단한 WHILE 루프이면 충분할 것입니다. 그러면 지금 가지고 계신 것처럼 당신의 예약/사용자 쿼리로 임시 테이블에 가입하십시오. 결과가 아직 예약되지 않은 채로 몇 개월이 걸릴 것입니다. 하나의 SELECT 문만 사용할 수 있다고 생각하지 않습니다.

0

가이 SQL Fiddle에서 입증 될 때 당신은 그것을 위해 하위 쿼리를 사용할 수 있습니다 : 당신의 문에 위의 쿼리를 적용

select y, n, concat(monthname(makedate(y, n*29)), ' ', y) yearmonth FROM 
(select n,y FROM 
(select 1 as n from dual 
Union All 
select 2 as n from dual 
Union All 
select 3 as n from dual 
Union All 
select 4 as n from dual 
Union All 
select 5 as n from dual 
Union All 
select 6 as n from dual 
Union All 
select 7 as n from dual 
Union All 
select 8 as n from dual 
Union All 
select 9 as n from dual 
Union All 
select 10 as n from dual 
Union All 
select 11 as n from dual 
Union All 
select 12 as n from dual) as months 
inner join (select distinct year(dt) y from test) as years on 1=1) AS ym 
left join test on month(dt) = n and year(dt) = y 
group by n, y order by y, n 

:

select y, n, concat(monthname(makedate(y, n*29)), ' ', y) yearmonth FROM 
(select n,y FROM 
(select 1 as n from dual 
Union All 
select 2 as n from dual 
Union All 
select 3 as n from dual 
Union All 
select 4 as n from dual 
Union All 
select 5 as n from dual 
Union All 
select 6 as n from dual 
Union All 
select 7 as n from dual 
Union All 
select 8 as n from dual 
Union All 
select 9 as n from dual 
Union All 
select 10 as n from dual 
Union All 
select 11 as n from dual 
Union All 
select 12 as n from dual) as months 
inner join (select distinct year(dt) y 
from bookings 
where date > DATE_SUB(CURDATE(), INTERVAL 11 MONTH) AND date <= CURDATE()) as years on 1=1) AS ym 
left join (
SELECT MONTH(bs.date) AS mth, YEAR(bs.date) as yr, count(*) AS Bookings, 
CONCAT(us.firstName,' ', us.lastName) as 'Name' 
from bookings bs RIGHT JOIN users us ON bs.clientID = us.recNo 
WHERE bs.managerID = 6 AND bs.clientID = 1900 
AND date > DATE_SUB(CURDATE(), INTERVAL 11 MONTH) AND date <= CURDATE() 
GROUP BY MONTH(bs.date), YEAR(bs.date)) as test on mth = n and yr = y 
group by n, y order by y, n 
관련 문제