1

我想生成以下数据集以用于 DataTables。为了使过滤和排序正常工作,即使不是不可能(据我所知),使用 JOINS 代替子查询也很困难。

申请人姓名、职位、面试官、面试1分数、面试2分数、Demo。分数、面试日期

以下是数据在 mySQL(简化版)中的存储方式:

申请人分数表

id  applicant_id    interviewer_id  score_type  score   datetime_recorded
 1             2                 3  Interview 1    80   2013-04-23 09:35:48
 2             2                45  Interview 1    70   2013-04-23 10:14:23
 3             2                 3  Interview 2    85   2013-04-23 09:35:48
 4             2                45  Interview 2    77   2013-04-23 10:14:23
 5             2                 3  Demonstration  76   2013-04-23 09:35:48
 6             3                45  Interview 1    79   2013-04-23 10:14:23
 7             3                 3  Interview 1    86   2013-04-23 09:35:48
 8             3                45  Interview 2    92   2013-04-23 10:14:23

申请人表

id  first_name  last_name
 2  John        Doe 
 3  Jane        Doe       

面试官桌

id  first_name  last_name
 3  Santa       Claus
45  Fred        Flintstone

申请人职位表

position_id   applicant_id
          1              2
          1              3

职位表

id  title                 
 1  Advanced mySQL Programmer

我已经尝试了所有我能想到的方法,但我无法正确按面试官和申请人对分数进行分组。我期望看到的是:

Applicant Name   Position                   Interviewer   Interview 1 Score  Interview 2 Score   Demo. Score  Interview Date
      John Doe   Advanced mySQL Programmer  Santa Claus                  80                 85            76      2013-04-23
      John Doe   Advanced mySQL Programmer  Fred Flintstone              70                 77                    2013-04-23
      Jane Doe   Advanced mySQL Programmer  Santa Claus                  86                                       2013-04-23
      Jane Doe   Advanced mySQL Programmer  Fred Flintstone              79                 92                    2013-04-23

这是我当前的查询,结果为零:

SELECT SQL_CALC_FOUND_ROWS 
       CONCAT( a.first_name, ' ', a.last_name), 
       p.title,
       CONCAT( i.first_name, ' ', i.last_name),
      (SELECT score FROM applicant_scores s, applicants a WHERE s.applicant_id = a.id AND s.score_type = 'Interview 1') as score_1, 
      (SELECT score FROM applicant_scores s, applicants a WHERE s.applicant_id = a.id AND s.score_type = 'Interview 2') as score_2, 
      (SELECT score FROM applicant_scores s, applicants a WHERE s.applicant_id = a.id AND s.score_type = 'Demonstration') as score_3, 
      (SELECT DATE_FORMAT(datetime_recorded, '%m-%d-%Y') FROM applicant_scores s, applicants a WHERE s.applicant_id = a.id) as interview_date
 FROM applicants a, positions p, interviewers i, applicant_scores s
 WHERE s.applicant_id = a.id AND i.id = s.interviewer_id
 GROUP BY i.id

这是用于提供 DataTables 的服务器端 ajax 代码...这是有关如何为 DataTables 创建服务器端脚本的信息 - http://www.datatables.net/release-datatables/examples/data_sources/server_side。 html

<?php
    /* Database connection information */
    $gaSql['user']       = "";
    $gaSql['password']   = "";
    $gaSql['db']         = "";
    $gaSql['server']     = "";

    $q1="'";
    $q2='"';

    $name = "CONCAT( ".$q2."<input type='hidden' id='name' value='".$q2.", LOWER(a.last_name), ' ', LOWER(a.first_name), ".$q2."'><input type='hidden' id='applicant_id' value='".$q2.", a.id, ".$q2."'><a href='applicant_details.php?id=".$q2.", a.id, ".$q2."'><img src='img/search.png' border='0'></a> &nbsp;".$q2.", a.last_name, ', ', a.first_name )";

    $interviewer = "CONCAT( ".$q2."<input type='hidden' id='name' value='".$q2.", LOWER(u.lastname), ' ', LOWER(u.firstname), ".$q2."'><input type='hidden' id='interviewer_id' value='".$q2.", i.id, ".$q2."'><a href='interviewer_details.php?id=".$q2.", i.id, ".$q2."'><img src='img/search.png' border='0'></a> &nbsp;".$q2.", u.lastname, ', ', u.firstname )";

    $int_1_score = "(SELECT score FROM applicant_scores s, applicants a WHERE s.applicant_id = a.id AND s.score_type = 'Interview 1' AND s.interviewer_id = i.id) as score_1";
    $int_2_score = "(SELECT score FROM applicant_scores s, applicants a WHERE s.applicant_id = a.id AND s.score_type = 'Interview 2' AND s.interviewer_id = i.id) as score_2";
    $demo_score = "(SELECT score FROM applicant_scores s, applicants a WHERE s.applicant_id = a.id AND s.score_type = 'Demonstration' AND s.interviewer_id = i.id) as score_3";

    $interview_date = "(SELECT DATE_FORMAT(datetime_recorded, '%m-%d-%Y') FROM applicant_scores s, applicants a WHERE s.applicant_id = a.id) as interview_date";

    $aColumns = array($name, 'p.title', $interviewer, $int_1_score, $int_2_score, $demo_score, $interview_date);

    /* Indexed column (used for fast and accurate table cardinality) */
    $sIndexColumn = "id";
    $sIndexTable = "formtemplates";

    /* DB table to use */
    $sTable = "applicants a, positions p, interviewers i, applicant_scores s, users u";

    $sWhere = " WHERE s.applicant_id = a.id AND i.id = s.interviewer_id AND u.id = i.user_id";

    $sGroupBy = " GROUP BY i.id";

    /* 
     * MySQL connection
     */
    $gaSql['link'] =  mysql_pconnect( $gaSql['server'], $gaSql['user'], $gaSql['password']  ) or
        die( 'Could not open connection to server' );

    mysql_select_db( $gaSql['db'], $gaSql['link'] ) or 
        die( 'Could not select database '. $gaSql['db'] );


    /* 
     * Paging
     */
    $sLimit = "";
    if ( isset( $_GET['iDisplayStart'] ) && $_GET['iDisplayLength'] != '-1' )
    {
        $sLimit = "LIMIT ".mysql_real_escape_string( $_GET['iDisplayStart'] ).", ".
            mysql_real_escape_string( $_GET['iDisplayLength'] );
    }

    /*
     * Ordering
     */
    if ( isset( $_GET['iSortCol_0'] ) )
    {
        $sOrder = " ORDER BY  ";
        for ( $i=0 ; $i<intval( $_GET['iSortingCols'] ) ; $i++ )
        {
            if ( $_GET[ 'bSortable_'.intval($_GET['iSortCol_'.$i]) ] == "true" )
            {
                if(stripos($aColumns[ intval( $_GET['iSortCol_'.$i] ) ], "c.name", 1) >= 1){
                    $sOrder .= "c.name ".mysql_real_escape_string( $_GET['sSortDir_'.$i] ).", ";
                }elseif(stripos($aColumns[ intval( $_GET['iSortCol_'.$i] ) ], "t.firstName", 1) >= 1){
                    $sOrder .= "t.firstName ".mysql_real_escape_string( $_GET['sSortDir_'.$i] ).", ";
                }elseif(stripos($aColumns[ intval( $_GET['iSortCol_'.$i] ) ], "d.shortName", 1) >= 1){
                    $sOrder .= "d.shortName ".mysql_real_escape_string( $_GET['sSortDir_'.$i] ).", ";
                }else{
                    $sOrder .= $aColumns[ intval( $_GET['iSortCol_'.$i] ) ]."
                    ".mysql_real_escape_string( $_GET['sSortDir_'.$i] ) .", ";
                }
            }
        }

        $sOrder = substr_replace( $sOrder, "", -2 );
        if ( $sOrder == "ORDER BY" )
        {
            $sOrder = "";
        }
    }


    /* 
     * Filtering
     * NOTE this does not match the built-in DataTables filtering which does it
     * word by word on any field. It's possible to do here, but concerned about efficiency
     * on very large tables, and MySQL's regex functionality is very limited
     */

    //define columns to filter on
    $aFcolumns = array( 'u.username', 'u.firstname', 'u.lastname', "REPLACE (g.status, 'OUT_FOR_SIGNATURE', 'WAITING')");

    if ( $_GET['sSearch'] != "" )
    {
        //$sWhere .= "WHERE (";
        $sWhere .= " AND (";
        for ( $i=0 ; $i<count($aFcolumns) ; $i++ )
        {
            $sWhere .= $aFcolumns[$i]." LIKE '%".mysql_real_escape_string( $_GET['sSearch'] )."%' OR ";
        }
        $sWhere = substr_replace( $sWhere, "", -3 );
        $sWhere .= ')';
    }


    /* Individual column filtering */
    for ( $i=0 ; $i<count($aFcolumns) ; $i++ )
    {
        if ( $_GET['bSearchable_'.$i] == "true" && $_GET['sSearch_'.$i] != '' )
        {
            if ( $sWhere == "" )
            {
                $sWhere = "WHERE ";
            }
            else
            {
                $sWhere .= " AND ";
            }
            $sWhere .= $aFcolumns[$i]." LIKE '%".mysql_real_escape_string($_GET['sSearch_'.$i])."%' ";
        }
    }


    /*
     * SQL queries
     * Get data to display
     */
    $sQuery = "
        SELECT SQL_CALC_FOUND_ROWS ".str_replace(" , ", " ", implode(", ", $aColumns))."
         FROM   $sTable
        $sWhere
        $sGroupBy       
        $sOrder 
        $sLimit
    ";

    //echo $sQuery;  die();  //for firebug debugging

    $rResult = mysql_query( $sQuery, $gaSql['link'] ) or die(mysql_error());

    /* Data set length after filtering */
    $sQuery = "
        SELECT FOUND_ROWS()
    ";
    $rResultFilterTotal = mysql_query( $sQuery, $gaSql['link'] ) or die(mysql_error());
    $aResultFilterTotal = mysql_fetch_array($rResultFilterTotal);
    $iFilteredTotal = $aResultFilterTotal[0];

    /* Total data set length */
    $sQuery = "
        SELECT COUNT(".$sIndexColumn.")
        FROM   $sIndexTable
    ";
    $rResultTotal = mysql_query( $sQuery, $gaSql['link'] ) or die(mysql_error());
    $aResultTotal = mysql_fetch_array($rResultTotal);
    $iTotal = $aResultTotal[0];

    /*
     * Output
     */
    $output = array(
        "sEcho" => intval($_GET['sEcho']),
        "iTotalRecords" => $iTotal,
        "iTotalDisplayRecords" => $iFilteredTotal,
        "aaData" => array()
    );

    while ( $aRow = mysql_fetch_array( $rResult ) )
    {
        $row = array();
        for ( $i=0 ; $i<count($aColumns) ; $i++ )
        {
            if ( $aColumns[$i] != ' ' )
            {
                /* General output */
                $row[] = $aRow[$i];
            }
        }

        //add another row for buttons
        //$row[] = "<div style='float:right;'><span style='padding-right:2px;'><a href=''><img src='global_img\user_info.png' border='0'></a></span><span style='padding-right:2px;'><a href=''><img src='global_img\user_edit.png' border='0'></a></span><span style='padding-right:0px;'><a href=''><img src='global_img\user_delete.png' border='0'></a></span></div>";

        $output['aaData'][] = $row;
    }

    echo json_encode( $output );
?>

我修改了服务器端脚本以尝试使用 bluefeet 提供的解决方案,以下是生成的查询:

        SELECT SQL_CALC_FOUND_ROWS concat(a.first_name, ' ', a.last_name), p.title, CONCAT(i1.first_name, ' ', i1.last_name), max(case when ac.score_type='Interview 1' then ac.score else '' end), max(case when ac.score_type='Interview 2' then ac.score else '' end), max(case when ac.score_type='Demonstration' then ac.score else '' end), DATE_FORMAT(ac.datetime_recorded, '%m-%d-%Y')
         FROM   applicants a
         inner join applicant_positions ap on a.id = ap.applicant_id inner join positions p on ap.position_id = p.id inner join applicant_scores ac on a.id = ac.applicant_id inner join interviewers i1 on ac.interviewer_id = i1.id 
         GROUP BY concat(a.first_name, ' ', a.last_name), p.title, CONCAT(i1.first_name, ' ', i1.last_name), DATE_FORMAT(ac.datetime_recorded, '%m-%d-%Y')      
         ORDER BY  concat(a.first_name, ' ', a.last_name)
                    asc 
        LIMIT 0, 500

这给了我一个空的结果集。帮助?

4

2 回答 2

5

你肯定在正确的轨道上得到结果。

您当前在查询中缺少一些连接。您需要加入applicantspositions使用applicant_positions表中。您还可以向applicant_scores表中添加一个连接,这将允许您使用带有 a 的聚合函数CASE来获取包含采访/演示分数的列:

select 
  concat(a.first_name, ' ', a.last_name) ApplicantName,
  p.title Position,
  CONCAT(i1.first_name, ' ', i1.last_name) Interviewer,
  max(case when ac.score_type='Interview 1' then ac.score else '' end) Interview1Score,
  max(case when ac.score_type='Interview 2' then ac.score else '' end) Interview2Score,
  max(case when ac.score_type='Demonstration' then ac.score else '' end) DemoScore,
  DATE_FORMAT(ac.datetime_recorded, '%m-%d-%Y') InterviewDate
from applicants a
inner join applicant_positions ap
  on a.id = ap.applicant_id
inner join positions p
  on ap.position_id = p.id
inner join applicant_scores ac
  on a.id = ac.applicant_id
inner join interviewers i1
  on ac.interviewer_id = i1.id
group by concat(a.first_name, ' ', a.last_name),
  p.title,
  CONCAT(i1.first_name, ' ', i1.last_name),
  DATE_FORMAT(ac.datetime_recorded, '%m-%d-%Y');

请参阅SQL Fiddle with Demo。这给出了结果:

| APPLICANTNAME |                  POSITION |     INTERVIEWER | INTERVIEW1SCORE | INTERVIEW2SCORE | DEMOSCORE | INTERVIEWDATE |
-------------------------------------------------------------------------------------------------------------------------------
|      Jane Doe | Advanced mySQL Programmer | Fred Flintstone |              79 |              92 |           |    04-23-2013 |
|      Jane Doe | Advanced mySQL Programmer |     Santa Claus |              86 |                 |           |    04-23-2013 |
|      John Doe | Advanced mySQL Programmer | Fred Flintstone |              70 |              77 |           |    04-23-2013 |
|      John Doe | Advanced mySQL Programmer |     Santa Claus |              80 |              85 |        76 |    04-23-2013 |
于 2013-04-23T16:29:32.030 回答
1
SELECT  CONCAT(b.first_name, ' ', b.last_Name) Applicant_Name,
        CONCAT(c.first_name, ' ', c.last_Name) Interviewer_Name,
        e.Title,
        MAX(CASE WHEN a.score_type = 'Interview 1' THEN a.score END) `Interview 1 Score`,
        MAX(CASE WHEN a.score_type = 'Interview 2' THEN a.score END) `Interview 2 Score`,
        MAX(CASE WHEN a.score_type = 'Demonstration' THEN a.score END) `Demonstration Score`,
        MAX(DATE(a.datetime_recorded)) `Interview Date`
FROM    applicant_scores a
        INNER JOIN applicants b
            ON a.applicant_ID = b.ID
        INNER JOIN interviewer c
            ON a.interviewer_ID = c.id
        INNER JOIN applicant_positions d
            ON a.applicant_ID = d.applicant_ID
        INNER JOIN positions e
            ON d.position_ID = e.ID
GROUP   BY  CONCAT(b.first_name, ' ', b.last_Name),
            CONCAT(c.first_name, ' ', c.last_Name),
            e.Title
于 2013-04-23T16:27:50.243 回答