需要在MYSQL中获取每个月的记录

时间:2016-06-09 05:07:00

标签: php mysql

我需要帮助从数据库中获取记录,但有一些条件,如下所述: -

我需要检查所选startDate和结束日期之间每个月的学生可用性。

表格结构: -

enter image description here

表数据: -

enter image description here

示例: -

例如,在这里,您可以将课堂容量作为20名学生。

我想查看从2016年2月2日到2017年4月的座位供应情况。

输出将是:

02/2016 - 20
03/2016 - 19
04/2016 - 18
05/2016 - 15
06/2016 - 20
.
.
.
02/2017 - 14
03/2017 - 20
04/2017 - 18

事先感谢您的帮助。

5 个答案:

答案 0 :(得分:7)

我发现你的问题是这样的,如果有多少学生,他们可以在一个月内的任何时间注册,这是不考虑的,但如果你可以决定将比较任何一个日期,如startDate或endDate这个查询肯定会帮助你。

SELECT count(*) as cnt,CONCAT(MONTH(startDate),'/',  YEAR(startDate)) as day from notes group by day 

我考虑过startDate。

如果我需要更多研究,请告诉我。

khajaamin

答案 1 :(得分:2)

您需要使用子查询或自联接来获取所需的结果,请参阅下面的示例:

SELECT LEFT(startDate,7) startMY, LEFT(endDate,7) endMY, (
    SELECT 20 - COUNT(*) FROM `tablename` B 
    WHERE LEFT(A.startDate,7) >= LEFT(B.startDate,7) AND 
          LEFT(A.endDate,7) <= LEFT(B.endDate,7)
) balanceCapacity FROM `tablename` A
GROUP BY LEFT(A.startDate,7), LEFT(A.endDate,7)

输出(基于屏幕截图中显示的记录):

+---------+---------+-----------------+
| startMY | endMY   | balanceCapacity |
+---------+---------+-----------------+
| 2015-12 | 2017-07 |              19 |
| 2016-03 | 2017-04 |              18 |
| 2016-05 | 2017-03 |              17 |
+---------+---------+-----------------+

答案 2 :(得分:1)

看起来这里的一些人提供的解决方案可以为您提供几个月内完全免费的结果(如果它们完全免费,则不会返回任何行)。

一个好的解决方案是返回每月占用的数字,然后在您的代码中构建您关注范围内的月份列表,并从相关月份的默认值中减去查询结果#34;完全免费&#34;值。

但是,如果你出于某种原因纯粹在MySQL中这样做非常重要,那么就没有通用的方法来说明&#34;给我一个给定范围内的值列表&#34 ;但是如果您不反对在执行查询之前构建一个您关心的月份列表,那么您可以使用大型union语句和左连接来执行此操作,例如:

SELECT Year, Month, {maxfree} - COUNT(whatever) FROM (
 SELECT 2016 AS Year, 1 AS Month
 UNION
 SELECT 2016 AS Year, 2 AS Month
 UNION
 ...
 etc
 ...
) AS MonthList
LEFT JOIN TableName
  ON YEAR(TableName.whatever) = MonthList.Year
  AND MONTH(TableName.whatever) = MonthList.Month
GROUP BY Year, Month

等等。以上内容需要进行大量修改以纠正模糊的列名等,并添加逻辑,以便跨越给定年份和月份的任何学生约会都包括在计数中并且它正确地解释了...其他答案已经这样做了,我不打算重做它:)

只考虑一种可能的方法,上述内容并不是直接作为答案。

答案 3 :(得分:1)

对于这个问题,我们设置了一个小型演示。

根据您的数据库截图enter image description here enter image description here

示例表架构,数据和查询

create table `test` (
`id` int(11),
`schoolid` int(11),
`classroomid` int(11),
`studentname` varchar(40),
`startmonth` int(2) unsigned zerofill,
`startyear` year,
`endmonth` int(2) unsigned zerofill,
`endyear` year);

insert into `test` (
`id`,
`schoolid`,
`classroomid`,
`studentname`,
`startmonth`,
`startyear`,
`endmonth`,
`endyear`) values (1,1,1,'ccc',3,2016,4,2017),
(2,1,2,'bbb',05,2016,3,2017),
(3,1,2,'aaa',12,2016,7,2017),
(4,1,2,'bbb',05,2016,3,2017),
(5,1,1,'bbb',09,2016,2,2017),
(6,1,2,'bbb',06,2016,4,2017),
(7,1,3,'bbb',03,2016,3,2017),
(8,1,3,'bbb',01,2016,1,2017),
(9,1,3,'bbb',11,2016,5,2017);

此查询会根据您的monthyear对,为您提供每个课程中可用的剩余席位。

select `classroomid`,'02' as `start_month`,'2016'`start_year`,'04'`end_month`,'2017'`end_year`,(20-count(`id`)) as `seats_left_in_class` from `test` where `startmonth`>=2 and `startyear`=2016 and `endmonth`<=4 and `endyear`=2017 group by `classroomid` order by `classroomid`;

您可以在SQL Fiddle

中查看示例结果

答案 4 :(得分:1)

您应该使用PHP来获取该范围内每个月的计数,仅SQL不会返回您需要的数据(轻松)。

使用SQL返回一个结果集,其中包含在您的范围之前或在您的范围之后结束的所有学生。

假设您的查询范围以$fromDate开头,以$toDate结尾:

SELECT startDate, endDate
FROM tableName
WHERE classroomID = $classroomID AND (
   (startDate BETWEEN $fromDate AND $toDate) OR
   (endDate BETWEEN $fromDate AND $toDate) OR
   (startDate < $fromDate AND endDate > $toDate)
)

然后使用PHP确定每个月范围内的座位数。

基本上循环播放范围内的每个月,并计算在该月之前或之前注册的所有学生,并且在该月之前注册尚未结束。

下面,我正在填充一个名为$enrollmentByMonth的数组,该数组将保存[year][month]存储的学生数量,然后从房间的容量中减去它们并存储在{{ 1}}

假设$openSeats[year][month]是从数据库返回的行数组:

$result

在此循环之后,打印所需信息是一件小事:

$year =     date('Y', $fromDate);
$month =    date('m', $fromDate);
$endYear =  date('Y', $toDate); 
$endMonth = date('m', $toDate);

$enrollmentByMonth = Array();
$openSeats = Array();

// loop through each month in range
while ($year <= $endYear){
    while ($year != $endYear || $month <= $endMonth){

        $loopDate = mktime(0, 0, 0, $month, 1, $year); // (hr,min,sec,mon,day,year)

        // loop through each db result row to tally up how
        // many students enrolled for every month/year combo
        foreach($result as $row){
            $rowStartDate = strtotime($row['startDate']);
            $rowEndDate = strtotime($row['endDate']);

            // if student registered prior to loopDate AND student
            // is still registered as of loopDate THEN count it
            if($rowStartDate <= $loopDate && $rowEndDate >= $loopDate){                 
                $enrollmentByMonth[$year][$month]++;
            }
        }

        $openSeats[$year][$month] = $roomCapacity - $enrollmentByMonth[$year][$month];

        $month++; 

        if($month > 12){
            $month=1;
            $year++;
        }
    }
}

抱歉,我没有时间对它进行测试,所以可能会有一个错字或者我忽略的东西,但希望这会指出你的方向很好......!