2014-06-05 36 views
0

以下是我所在的三个表,其中session.id = signup.session_id AND session.loc_id = location.id。最大覆盖范围正如名称建议覆盖位置的默认最大容量,因此IFNULL(session.max_override, location.max_cap)按日期分组并合并3个表中的数据

mysql> SELECT * FROM session; 
+----+---------------------+---------------+--------+ 
| id | date_time   | max_override | loc_id | 
+----+---------------------+---------------+--------+ 
| 1 | 2014-02-04 10:30:00 |  35  | 2 | 
| 2 | 2014-02-04 17:00:00 |    | 2 | 
| 3 | 2014-02-06 11:30:00 |  50  | 2 | 
| 4 | 2014-02-09 13:30:00 |    | 1 | 
+----+---------------------+---------------+--------+ 

mysql> SELECT * FROM location; 
+-----------------+---------+ 
| id | location | max_cap | 
+-----------------+---------+ 
| 1 | up   | 20  | 
| 2 | down  | 103  | 
| 3 | right  | 50  | 
| 4 | left  | 50  | 
+-----------------+---------+ 

mysql> SELECT * FROM signups; 
+-----------------+------------+ 
| id | name  | session_id | 
+-----------------+------------+ 
| 1 | test  | 3  | 
| 2 | admin  | 1  | 
| 3 | meme  | 2  | 
| 4 | anna  | 4  | 
+-----------------+------------+ 

我想创建的报告看起来很简单,但我不确定如何解决问题。以下是我怎么想的报告/输出的样子..

mysql> query ouput; 
+------------+----------+-----------+----------+----------+-----------+----------+ 
| date  | am_time | am_ses_id | am_spots | pm_time | pm_ses_id | pm_spots | 
+------------+----------+-----------+----------+----------+-----------+----------+ 
| 2014-02-04 | 10:30 AM | 1  | 34 | 05:00 PM |  2  | 102 | 
| 2014-02-06 | 11:30 AM | 3  | 49 |   |   |   | 
| 2014-02-09 |   |   |   | 01:30 PM |  4  | 49 | 
+------------+----------+-----------+----------+----------+-----------+----------+ 

我能集团的日期和时间正确,并设法让session_id匹配,因为它是所有中的一个表,但是计算上午/下午点只是计算特定会话的注册表中的记录,并根据具体情况从max_capmax_override中扣除值。

这是我试过

使用下面的查询

SELECT 
    DATE_FORMAT(a.date_time,'%m/%d/%Y') AS ses_date, 
    DATE_FORMAT(a.date_time,'%r') AS ses_time, 
    a.id, 
    COUNT(b.id) as signed_up, 
    IFNULL(a.max_override,c.max_cap) AS cap 
FROM 
    test.session a 
    LEFT JOIN 
     test.signups b 
     ON (b.session_id = a.id) 
    LEFT JOIN 
     test.location c 
     ON (c.id = a.loc_id) 
GROUP BY b.session_id 

我得到以下输出

+------------+----------+--------+-----------+------+ 
| date  | ses_time | ses_id | signed_up | cap | 
+------------+----------+--------+-----------+------+ 
| 2014-02-04 | 10:30 AM | 1 | 1  | 35 | 
| 2014-02-04 | 05:00 PM | 2 | 1  | 103 | 
| 2014-02-06 | 10:30 AM | 3 | 1  | 50 | 
| 2014-02-09 | 10:30 AM | 4 | 1  | 50 | 
+------------+----------+--------+-----------+------+ 

我似乎但是不能找到一种方法来组只由日期,所以输出将显示为想要的!我不知道我是否应该结合两个查询。

+0

什么am_spots和pm_spots? – Fabricator

+0

'JOIN'运算符让SQL知道如何关联这些表。 – serakfalcon

+0

这些只是am(上午)会议或pm(下午)会议的计算点。它通过计算注册表中的记录并从max_override(如果设置)或从位置表中的max_cap中扣除它来计算。 – rakesh219

回答

1

这里是做的非常令人费解的方式...

sqlfiddle:http://sqlfiddle.com/#!2/d85ca/11

select c.ses_date `date`, a.ses_time am_time, a.id am_ses_id, a.cap-a.signed_up am_spots, 
     b.ses_time pm_time, b.id pm_ses_id, b.cap-b.signed_up pm_spots 
from (
    select distinct DATE_FORMAT(a.date_time,'%m/%d/%Y') ses_date 
    from session a) c 
left join (
    SELECT 
     DATE_FORMAT(a.date_time,'%m/%d/%Y') AS ses_date, 
     DATE_FORMAT(a.date_time,'%r') AS ses_time, 
     a.id, 
     COUNT(b.id) as signed_up, 
     IFNULL(a.max_override,c.max_cap) AS cap 
    FROM 
     session a 
     LEFT JOIN 
      signups b 
      ON (b.session_id = a.id) 
     LEFT JOIN 
      location c 
      ON (c.id = a.loc_id) 
    where date_format(a.date_time, '%p') = 'AM' 
    GROUP BY b.session_id) a on c.ses_date = a.ses_date 
left join (
    SELECT 
     DATE_FORMAT(a.date_time,'%m/%d/%Y') AS ses_date, 
     DATE_FORMAT(a.date_time,'%r') AS ses_time, 
     a.id, 
     COUNT(b.id) as signed_up, 
     IFNULL(a.max_override,c.max_cap) AS cap 
    FROM 
     session a 
     LEFT JOIN 
      signups b 
      ON (b.session_id = a.id) 
     LEFT JOIN 
      location c 
      ON (c.id = a.loc_id) 
    where date_format(a.date_time, '%p') = 'PM' 
    GROUP BY b.session_id) b on c.ses_date = b.ses_date; 
+0

看到了,所有这些工作,而且这是UI可以简单地解决的问题。 – serakfalcon

+0

这很难读!但由于它看起来是最好的方式,我会尽力去做。感谢LOT对此的快速反应! – rakesh219

0

您需要使用JOIN运算符让SQL DB知道表之间的关系。 在这种情况下,可能会更容易做一个子查询来计算(以避免GROUP BY)。我没有白天把AM和PM分开,但你可以做到这一点。

SELECT session.date_time, 
    IFNULL(session.max_override,location.max_cap)-(
     SELECT COUNT(signups.id) 
     FROM signups 
     WHERE signups.session_id = session.id) as avail_spots 
FROM session LEFT JOIN location ON session.loc_id = location.id; 

LEFT JOIN将包括2014-02-04 17:00:00以来既不max_override一个NULL avail_spots也不max_cap有一个值,而INNER JOIN不会在所有的报告会。

fiddle

编辑:一旦你一天掌握的信息,你可以用它输出。试图摆脱时代的束缚,但在日期上进行分组会增加查询的复杂性,这可以通过您使用的任何程序更简单地解决。

+0

我需要将输出放入网格中,但为了使其正常工作,查询结果必须一致。感谢您的输入!我会采取你的建议,并尝试开发由user3678068给出的代码!再次感谢! – rakesh219

+0

按日期排序,您可以使用此查询制作网格,而不会增加复杂性。你正在让SQL做额外的工作以获得额外的好处。 – serakfalcon