mySQL复杂的连接和偶数枢轴

时间:2013-10-01 04:48:48

标签: mysql join pivot

我正在研究班次调度解决方案,需要你的帮助。 数据库布局如下所示:database-layout

我查询一个月的所有时间表如下所示:

SELECT
    ca.date,
    ss.num,
    ma.name
FROM dp_dienstplan  AS dp
JOIN ma_mitarbeiter AS ma ON ma.id=dp.dp_mitarbeiter_id
JOIN ss_schienen    AS ss ON ss.id=dp.dp_schienen_id
JOIN sc_schicht     AS sc ON sc.id=ss.ss_schicht_id
RIGHT JOIN calendar AS ca ON ca.date=dp.dp_datum
WHERE
  month(ca.date)=9 AND year(ca.date)=2013

日历表是一个帮助表,其中包含接下来几年的日期,以便在未安排任何计划的结果中获得偶数天。

查询的结果如下所示:

date       |num        |name
----------------------------
2013-09-01  NULL        NULL
2013-09-02  2           foo
2013-09-02  3           bar
2013-09-03  2           uncle
2013-09-03  1           mac
2013-09-03  7           super
2013-09-04  NULL        NULL
2013-09-04  2           master
.
.
.
2013-09-30  NULL        NULL

我梦寐以求的结果如下:

date       |1num |1name |2num |2name |3num |3name. . .|7name|7num 
-----------------------------------------------------------------
2013-09-01  NULL  NULL   NULL  NULL   NULL  NULL . . . NULL  NULL
2013-09-02  NULL  NULL   2     foo    3     bar  . . . NULL  NULL
2013-09-03  1     mac    2     uncle  NULL  NULL . . . 7     super
2013-09-04  NULL  NULL   2     master NULL  NULL . . . NULL  NULL
.           .     .      .     .      .     .          .     . 
.           .     .      .     .      .     .          .     . 
.           .     .      .     .      .     .          .     . 
2013-09-30  NULL  NULL   NULL  NULL   NULL  NULL . . . NULL  NULL

每一天应该有一行,名称和'num'值的顺序。 我希望你理解我在说什么,抱歉我的英语。

我有另一个帮助表,其中包含1到200的值,我试图右键加入,但我没有成功。

提前致谢,对不起,如果这是一个重复的问题,我没有在谷歌或论坛上找到任何结果,也许是因为我不知道要搜索什么。

干杯,拉尔夫。

1 个答案:

答案 0 :(得分:0)

首先不要将函数应用于用于在WHERE子句中过滤数据的列。它可以防止MySQL在该列上使用您可能拥有的任何索引,从而有效地在表上执行fullscan。这是说而不是

WHERE month(ca.date)=9 AND year(ca.date)=2013

你最好做点什么

WHERE ca.date BETWEEN '2013-09-01' AND LAST_DAY('2013-09-01')

并确保您在calendar.datedp_dienstplan.dp_datum上有索引。


现在如果预先知道ss.num的所有值,您可以通过在静态查询中使用条件聚合来获取您的支点

SELECT ca.date,
       MAX(CASE WHEN ss.num = 1 THEN ss.num  END) `1num`,
       MAX(CASE WHEN ss.num = 1 THEN ss.name END) `1name`,
       MAX(CASE WHEN ss.num = 2 THEN ss.num  END) `2num`,
       MAX(CASE WHEN ss.num = 2 THEN ss.name END) `2name`,
       MAX(CASE WHEN ss.num = 3 THEN ss.num  END) `3num`,
       MAX(CASE WHEN ss.num = 3 THEN ss.name END) `3name`,
       MAX(CASE WHEN ss.num = 4 THEN ss.num  END) `4num`,
       MAX(CASE WHEN ss.num = 4 THEN ss.name END) `4name`,
       MAX(CASE WHEN ss.num = 5 THEN ss.num  END) `5num`,
       MAX(CASE WHEN ss.num = 5 THEN ss.name END) `5name`,
       MAX(CASE WHEN ss.num = 6 THEN ss.num  END) `6num`,
       MAX(CASE WHEN ss.num = 6 THEN ss.name END) `6name`,
       MAX(CASE WHEN ss.num = 7 THEN ss.num  END) `7num`,
       MAX(CASE WHEN ss.num = 7 THEN ss.name END) `7name`
  FROM dp_dienstplan  AS dp
   JOIN ma_mitarbeiter AS ma ON ma.id=dp.dp_mitarbeiter_id
   JOIN ss_schienen    AS ss ON ss.id=dp.dp_schienen_id
   JOIN sc_schicht     AS sc ON sc.id=ss.ss_schicht_id
   RIGHT JOIN calendar AS ca ON ca.date=dp.dp_datum
WHERE ca.date BETWEEN '2013-09-01' AND LAST_DAY('2013-09-01')
GROUP BY ca.date

输出:

|       DATE |   1NUM |  1NAME |   2NUM |  2NAME |   3NUM |  3NAME |   4NUM |  4NAME |   5NUM |  5NAME |   6NUM |  6NAME |   7NUM |  7NAME |
|------------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|
| 2013-09-01 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) |
| 2013-09-02 | (null) | (null) |      2 |    foo |      3 |    bar | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) |
| 2013-09-03 |      1 |    mac |      2 |  uncle | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) |      7 |  super |
| 2013-09-04 | (null) | (null) |      2 | master | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) |
| 2013-09-30 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) |

以下是 SQLFiddle 演示在此演示中,所有联接的表都由一个表模拟,其中包含您根据查询显示的示例数据