2012-03-22 6 views
1

쿼리에 대한 브레인 스토밍에 대한 약간의 도움이 필요합니다. 각 레스토랑 위치에 대해 두 행 (하루)이있는 판매 테이블이 있습니다. 한 행은 AM 판매이고 다른 행은 PM 판매입니다. AM 판매량은 문자 그대로 AM 판매량이지만, PM 판매량은 AM 판매량과 PM 판매량의 조합입니다. 따라서 PM 판매를 추출하려면 AM 판매 행을 빼야합니다.MySQL 쿼리 - 두 행의 차이

--------------------------------------------------------- 
    date | id | meridiem | daily_sales | cover_counts | 
--------------------------------------------------------- 
2012-03-22 |103 | AM  | 2956.32 | 175  | 
2012-03-22 |103 | PM  | 12124.62 | 484  | 
--------------------------------------------------------- 

AM 판매액에서 예상되는 점심 시간을 계산할 수있는 쿼리가 있는데 잘 작동합니다. 기본적으로 판매 데이터의 마지막 6 주부터 처음 4 주를 추출하여 평균합니다. (참고 : 1 인당 평균은 판매를 커버로 나누어 계산합니다.)

$statement = "SELECT directory.location, ROUND((SUM(sales.daily_sales/sales.cover_counts)/4), 2) AS lppa 
       FROM t_directory directory 
       LEFT JOIN t_sales sales 
       ON sales.site_id = directory.site_id 
       AND DAYOFWEEK(sales.business_date) = DAYOFWEEK(:date1) 
       AND sales.business_date < DATE_SUB(:date2, INTERVAL 14 DAY) 
       AND sales.business_date >= DATE_SUB(:date3, INTERVAL 42 DAY)     
       AND sales.meridiem = 'AM' 
       WHERE directory.active = 1 
       GROUP BY directory.site_id 
       ORDER BY directory.site_id ASC 
       LIMIT :totalLocations"; 

$statementHandle = $this->dbHandle->prepare($statement); 
$statementHandle->bindValue(':date1', $this->date, PDO::PARAM_STR); 
$statementHandle->bindValue(':date2', $this->date, PDO::PARAM_STR); 
$statementHandle->bindValue(':date3', $this->date, PDO::PARAM_STR); 
$statementHandle->bindValue(':totalLocations', $this->totalLocations, PDO::PARAM_INT); 
$statementHandle->execute(); 
$lppa = $statementHandle->fetchAll(PDO::FETCH_ASSOC); 

이제 일인당 저녁 식사를 계산하고 싶습니다. 이렇게하기 위해서는 수학과 계산법이 모두 적용되기 전에 AM 판매량과 PM 판매량을 감안해야합니다. 이 모든 것을 하나의 쿼리로 구현하는 다소 간단한 방법이 있습니까? 필자는 분명히 PHP로이 작업을 수행 할 수 있지만 쿼리에서이 작업을 수행하는 방법에 대해 궁금합니다. 어떤 도움이나 통찰력이라도 대단히 감사하겠습니다. 더 자세한 정보가 필요한지 알려주십시오.

답변

2

당신 다시 t_sales에 가입 할 다음 '오후'를 필터링 할 수

SELECT DIRECTORY.location, 
     Round((SUM(salesPM.daily_sales - salesAM.daily_sales/
        salesPM.cover_counts - salesAM.cover_counts)/4), 2) 
         AS lppaPM 
FROM t_directory DIRECTORY 
     LEFT JOIN t_sales salesAM 
     ON salesAM.site_id = DIRECTORY.site_id 
      AND Dayofweek(salesAM.business_date) = Dayofweek(:date1) 
      AND salesAM.business_date < DATE_SUB(:date2, INTERVAL 14 DAY) 
      AND salesAM.business_date >= DATE_SUB(:date3, INTERVAL 42 DAY) 
      AND salesAM.meridiem = 'AM' 
     LEFT JOIN t_sales salespm 
     ON salesAM.site_id = salesPM.site_id 
      AND salesAM.business_date = salesPM.business_date 
      AND salespm.meridiem = 'PM' 
WHERE DIRECTORY.active = 1 
GROUP BY DIRECTORY.site_id 
ORDER BY DIRECTORY.site_id ASC 
LIMIT :totalLocations 

참고 :이 솔루션은

  • {Site_ID, business_Date, meridiem}이 고유
  • 는 PM이 결코
  • 것으로 가정 AM 레코드가없는 레코드
  • salesPM.cover_counts - salesAM.cover_counts는 0이 아닙니다.
+0

@Brett을 - - (콘래드에 메모), 올바른 커버를 얻으려면 PM 커버에서 아침 커버를 뺀다. o 저녁에 얼마나 많은 식사를하는 사람이 있는지 알고 계신가요? – DRapp

+0

@DRapp 감사합니다. 업데이트 하겠지만, 방금 Andomor의 솔루션을 보면서 faceplam을했습니다. –

+0

나는이 합계가 정확하게 합쳐 졌다고 생각하지 않습니다. 두 번째 왼쪽 조인에는 첫 번째 왼쪽 조인의 각 행에 대한 반복 행이 포함됩니다. – Andomar

1

은 조인 조건에서이를 제거

AND sales.meridiem = 'AM' 

그런 다음 당신이 선택할 수 있습니다

ROUND((SUM(case when sales.meridiem = 'AM' 
       then sales.daily_sales/sales.cover_counts end)/4), 2) as AMSum 
ROUND((SUM(case when sales.meridiem = 'PM' 
       then sales.daily_sales/sales.cover_counts end)/4), 2) as PMSum 

이 PM에서 AM을 빼려면, 당신은 할 수 :

SUM(case sales.meridiem 
    when 'PM' then sales.daily_sales/sales.cover_counts 
    when 'AM' then - sales.daily_sales/sales.cover_counts 
    end) as am_minus_pm 
+0

PM에서 AM을 뺄 위치는 어디입니까? – Brett