从Schedule表中获取多个COUNTS多个JOINS

时间:2014-03-10 05:38:13

标签: mysql join group-by

我有3张桌子:

test_membertest_member_addon& test_schedule

  • 一个成员只能有1个test_member.Type(test_schedule.prod_type = 1)
  • 成员可以有多个test_member_addon.Type (test_schedule.prod_type = 2)

我正在尝试为未来日期和schedule的计划中的每个DISTINCT test_schedule.mem_ID,test_schedule.Prod_Code返回Distinct Counts。status = 1.

时间表应该有正确的付款金额,例如。 52为'每周'。如果Correct& Actual不匹配,我可以解决。

我的查询:未为AmountPeriodCorrectActual返回正确的值。

SELECT DISTINCT s.mem_ID,
CASE WHEN s.prod_type = 1 THEN ROUND(m.next_amount,2) ELSE ROUND(ma.next_amount,2) END AS Amount, 
CASE WHEN s.prod_type = 1 THEN m.Period ELSE ma.Period END AS Period,
CASE WHEN s.prod_type = 1 THEN 
(
CASE WHEN m.Period = 'Weekly' THEN 52 
WHEN m.Period = 'Fortnightly' THEN 27 END
)
ELSE
(
CASE WHEN ma.Period = 'Weekly' THEN 52 
WHEN ma.Period = 'Fortnightly' THEN 27 END 
)
END AS Correct,
COUNT(*) AS Actual, 
s.prod_code, 
s.prod_type
FROM `test_schedule` s, `test_member` m, `test_member_addon` ma 
WHERE m.ID = s.mem_ID AND ma.mem_ID = m.ID 
AND s.status = 1 
GROUP BY s.prod_code, s.mem_ID 
ORDER BY s.mem_ID, s.prod_type;

数据库构建脚本:

CREATE TABLE `test_member` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `next_amount` float DEFAULT NULL,
  `period` varchar(50) DEFAULT NULL,
  `prod_code` int(11) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

INSERT INTO `test_member` (`ID`, `next_amount`, `period`, `prod_code`) VALUES
('1','50','Weekly',11),
('2','35','Fortnightly',11);

CREATE TABLE `test_member_addon` (
  `mem_addon_ID` int(11) NOT NULL AUTO_INCREMENT,
  `mem_ID` int(11) DEFAULT NULL,
  `next_amount` float DEFAULT NULL,
  `period` varchar(50) DEFAULT NULL,
  `prod_code` int(11) NOT NULL,
  PRIMARY KEY (`mem_addon_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;

INSERT INTO `test_member_addon` (`mem_addon_ID`, `mem_ID`, `next_amount`, `period`, `prod_code`) VALUES
('1','1','25.55','Weekly',22),
('2','1','15','Fortnightly',33);

CREATE TABLE `test_schedule` (
  `sched_ID` int(11) NOT NULL AUTO_INCREMENT,
  `mem_ID` int(11) NOT NULL,
  `prod_code` int(11) NOT NULL,
  `prod_type` int(11) NOT NULL,
  `status` smallint(4) NOT NULL,
  `amount` float NOT NULL,
  `sched_date` date NOT NULL,
  PRIMARY KEY (`sched_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=latin1;

INSERT INTO `test_schedule` (`sched_ID`, `mem_ID`, `prod_code`, `prod_type`, `status`, `amount`, `sched_date`) VALUES
('1','1','11','1','1','50','2014-03-21'),
('2','1','11','1','1','50','2014-03-28'),
('3','1','11','1','1','50','2014-04-04'),
('4','1','11','1','1','50','2014-04-11'),
('5','1','11','1','1','50','2014-04-18'),
('6','1','22','2','1','25.55','2014-03-21'),
('7','1','22','2','1','25.55','2014-03-28'),
('8','1','22','2','1','25.55','2014-04-04'),
('9','1','22','2','1','25.55','2014-04-11'),
('10','1','22','2','1','25.55','2014-04-18'),
('11','1','22','2','1','25.55','2014-04-25'),
('12','1','22','2','1','25.55','2014-05-02'),
('13','1','22','2','1','25.55','2014-05-09'),
('14','1','33','2','1','15','2014-03-21'),
('15','1','33','2','1','15','2014-04-04'),
('16','1','33','2','1','15','2014-04-18'),
('17','1','33','2','1','15','2014-05-02'),
('18','1','33','2','1','15','2014-05-16'),
('19','1','33','2','1','15','2014-05-30'),
('20','1','33','2','1','15','2014-06-13'),
('21','1','33','2','1','15','2014-06-27');

Current Return Data:
mem_ID |    Amount   |    Period    | Correct  |  Actual  |prod_code | prod_type
1      |    50.00    |    Weekly    |    52    |    10    |    11    |    1
1      |    25.55    |    Weekly    |    52    |    16    |    22    |    2
1      |    25.55    |    Weekly    |    52    |    16    |    33    |    2 

Correct Data:
mem_ID |    Amount   |    Period    | Correct  |  Actual  |prod_code | prod_type
1      |    50.00    |    Weekly    |    52    |    5     |    11    |    1
1      |    25.55    |    Weekly    |    52    |    8     |    22    |    2
1      |    15       | Fortnightly  |    27    |    8     |    33    |    2 

1 个答案:

答案 0 :(得分:1)

以这种方式试试

SELECT mem_id, prod_code, prod_type, period, 
       ROUND(MAX(amount), 2) amount, 
       CASE WHEN period = 'Weekly' THEN  52 ELSE 27 END correct,      
       COUNT(*) actual
  FROM
(
  SELECT s.*, m.period
    FROM test_schedule s JOIN test_member m
      ON s.mem_id = m.id 
     AND s.prod_code = m.prod_code
     AND s.prod_type = 1
   WHERE s.status = 1 
  UNION ALL 
  SELECT s.*, a.period
    FROM test_schedule s JOIN test_member_addon a 
      ON s.mem_id = a.mem_id 
     AND s.prod_code = a.prod_code
     AND s.prod_type = 2
   WHERE s.status = 1 
) q
 GROUP BY mem_id, prod_code, prod_type, period

输出:

| MEM_ID | PROD_CODE | PROD_TYPE |      PERIOD | AMOUNT | CORRECT | ACTUAL |
|--------|-----------|-----------|-------------|--------|---------|--------|
|      1 |        11 |         1 |      Weekly |     50 |      52 |      5 |
|      1 |        22 |         2 |      Weekly |  25.55 |      52 |      8 |
|      1 |        33 |         2 | Fortnightly |     15 |      27 |      8 |

这是 SQLFiddle 演示