我想生成以下数据集以用于 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> ".$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> ".$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
这给了我一个空的结果集。帮助?