0

I have 2 tables

CREATE TABLE `employee` (
  `Employee_ID` smallint(4) NOT NULL AUTO_INCREMENT,
  `Name` varchar(25) NOT NULL DEFAULT '',
  PRIMARY KEY (`Employee_ID`)
) ;  
--- -----------------  
CREATE TABLE `attendance` (
  `Attendance_ID` int(9) NOT NULL AUTO_INCREMENT,
  `Employee_ID` smallint(3) NOT NULL,
  `Date` date NOT NULL,
  `Attendance` char(1) NOT NULL DEFAULT '',
  PRIMARY KEY (`Attendance_ID`)
) ;  

For Attendance field it's a "P" when the employee is present "L" when late and "A" when absent.
I want to make a query that crosses the dates with employees names and show atendance.
Something similar to:

Attendance 07/02/2015   14/02/2015    21/02/2015  ...  
Diane           P           P               L  
Robert          A           P               P  
Karine          P           P               A  
...         

I didn't post any query because actually I failed many times to figure out how to Thanks for help

SamT
  • 10,374
  • 2
  • 31
  • 39
Lebon
  • 33
  • 4
  • You need to create [a dynamic pivot query](https://stackoverflow.com/questions/14834290/mysql-query-to-dynamically-convert-rows-to-columns/14834322#14834322) In the linked example, you would substitute `Date` for the `order` concatenated in the `as`. – Michael Berkowski Feb 17 '15 at 17:33
  • Are you always going to show a fixed number of weeks in the results? – shawnt00 Feb 17 '15 at 17:54
  • No the number of weeks will increase with time, until the end of the school year. Thanks – Lebon Feb 17 '15 at 21:01
  • Thank you SamT for formatting my question. For dynamic sql I didn't use it before so frankly I didn't give it a try since my knowledge is limitted – Lebon Feb 17 '15 at 21:05

3 Answers3

0

I do not know how to get dynamic columns in MySQL. This is how I would do it:

SELECT attd.Date, attd.Attendance, empl.Name FROM attendance attd, employee empl WHERE empl.Employee_ID = attd.Employee_ID

That will give result:

enter image description here

Then I would use server side code (example PHP):

<?php
$attendance = array();
foreach ($query as $row) {
    if (isset($attendance[$row['Name']])) {
        $attendance[$row['Name']][$row['Date']] = $row['Attendance'];
    } else {
        $attendance[$row['Name']] = array($row['Date'] => $row['Attendance']);
    }
}

print_r($attendance);

/* Array(
    "Diane" => Array("2015-02-07" => 'P', "2015-02-14" => 'P'),
    "Robert" => Array("2015-02-07" => 'P', "2015-02-14" => 'P'),
    "Karine" => Array("2015-02-07" => 'L', "2015-02-14" => 'L')
  )
*/
Ananth
  • 4,227
  • 2
  • 20
  • 26
  • Thanks for the help, I followed your method and the result shows: Array ( ) just an empty array even if I have records – Lebon Feb 17 '15 at 20:58
  • Did you run the sql query and check if it is giving the output in that format? – Ananth Feb 17 '15 at 21:58
  • Yes I ran the sql query and it worked fine as yours. I used your php code but still the result is=> Array( ). Wondering if something wrong with php code. Thanks Ananth – Lebon Feb 18 '15 at 01:34
  • Could you please test from your side. Thanks – Lebon Feb 18 '15 at 15:43
  • You should use `print_r($row);` in the foreach loop, check what $row contains and adjust the array lines based on that output. – Ananth Feb 19 '15 at 06:59
0
select 
    a.Employee_ID,
    min(e.Name) as Employee_Name,
    case when a.Date = dateadd(:basedate, interval 7*0 day) then min(a.Attendance) end as d0 /* d for data? */
    case when a.Date = dateadd(:basedate, interval 7*1 day) then min(a.Attendance) end as d1
    case when a.Date = dateadd(:basedate, interval 7*2 day) then min(a.Attendance) end as d2
    case when a.Date = dateadd(:basedate, interval 7*3 day) then min(a.Attendance) end as d3
    dateadd(:basedate, interval 7*0 day) as week0
    dateadd(:basedate, interval 7*1 day) as week1
    dateadd(:basedate, interval 7*2 day) as week2
    dateadd(:basedate, interval 7*3 day) as week3
from
    attendance as a inner join employee as e ...
where a.Date between :basedate and dateadd(:basedate, interval 7*3 day)
group by
    a.Employee_ID

You could pass in a :basedate parameter and offset a fixed number of weeks from that point. (I don't know what's the parameter convention for PHP and MySQL.) This will work if you can fix your results to a set number of weeks.

Pick out the dates from the first row to build the header and then build the rest of the table as you normally would. Yes there's some redundant data but there's no easy way to alias the columns with the dates themselves.

shawnt00
  • 16,443
  • 3
  • 17
  • 22
0

Following query you can use to gain the shown output along with a bit of PHP application

SELECT E.Name, A.Date, A.Attendance
FROM attendance AS A
INNER JOIN employee AS E
ON A.Employee_ID = E.Employee_ID
ORDER BY A.Date, E.Name

For implementing this in PHP

<?php

if (!$link = mysql_connect('< mysql_host >', '< mysql_user >', '< mysql_password >')) {
    echo 'Could not connect to mysql';
    exit;
}

if (!mysql_select_db('< mysql_dbname >', $link)) {
    echo 'Could not select database';
    exit;
}

$sql    =   'SELECT E.Name, A.Date, A.Attendance '.
            'FROM attendance AS A '.
            'INNER JOIN employee AS E '.
            'ON A.Employee_ID = E.Employee_ID '.
            'ORDER BY E.Name, A.Date';

$result = mysql_query($sql, $link);

if (!$result) {
    echo "DB Error, could not query the database\n";
    echo 'MySQL Error: ' . mysql_error();
    exit;
}

$name = '';
$resultArray = array();

$attendance = array();
foreach ($query as $row) {
    if (isset($attendance[$row['Name']])) {
        array_push($attendance[$row['Name']], $row['Date'] => $row['Attendance']);
    } else {
        $attendance[$row['Name']] = array($row['Date'] => $row['Attendance']);
    }
}

print_r($attendance);

mysql_free_result($result);

?>

You would get an a associative array like this

Array(
    "Diane" => Array("2015-02-07" => 'P', "2015-02-14" => 'P'),
    "Robert" => Array("2015-02-07" => 'P', "2015-02-14" => 'P'),
    "Karine" => Array("2015-02-07" => 'L', "2015-02-14" => 'L')
)

Now you can use this associative array to in a loop to render these elements in the Web page

Hope this helps...

Benison Sam
  • 2,755
  • 7
  • 30
  • 40
  • Thanks after running this I got only an empty array even if I have records. Result shows: Array( ) – Lebon Feb 17 '15 at 21:00
  • Could you please test from your side. Thanks – Lebon Feb 18 '15 at 15:43
  • I've made a change. Can you please test it out? Also check whether the query is returning any results or not using [var_dump](http://php.net/manual/en/function.var-dump.php). – Benison Sam Feb 22 '15 at 06:25