SQL, MySQL and php - mysql

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

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:
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')
)
*/

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.

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...

Related

How to merge 2 column into 1 column TO output in SQL

I have this sql query:
$sql = "SELECT d.doctor_name, a.patient_name, s.date, s.time FROM appointments AS a LEFT JOIN doctors AS d ON d.id = a.doctor_id LEFT JOIN slots AS s ON s.id = a.slot_id WHERE s.date > '2019-10-01' ORDER BY d.doctor_name DESC ";
$result = $mysqli->query($sql);
echo '<pre>';
while ( $row = $result->fetch_assoc() ) {
print_r($row);
}
echo '</pre>';
and it's output is:
Array
(
[doctor_name] => Khaled
[patient_name] => Nawaz
[date] => 2019-10-11
[time] => 02:01
)
Array
(
[doctor_name] => Khaled
[patient_name] => Anik
[date] => 2019-10-07
[time] => 02:31
)
Array
(
[doctor_name] => Khaled
[patient_name] => Manik
[date] => 2019-10-02
[time] => 03:31
)
Can I merge the date and time column as slot_date_time?
So output will be e.g:
Array
(
[doctor_name] => Khaled
[patient_name] => Manik
[slot_date_time] => 2019-10-02 03:31
)
Try this query
SELECT d.doctor_name, a.patient_name, CONCAT(s.date, ',', s.time) AS slot_date_time
FROM appointments AS a LEFT JOIN doctors AS d
ON d.id = a.doctor_id LEFT JOIN slots AS s
ON s.id = a.slot_id
WHERE s.date > '2019-10-01'
ORDER BY d.doctor_name DESC
Use CONCAT for merge two column as one column

With eloquent to make search by 2 fields

Is there a way in Laravel 5.6/MySQL 5.7 with eloquent to make search with condition:
need to check if sale_price is set then search in sale_price else in retail_price
Have I use condition like :
\DB::raw( ‘ isNull( sale_price, retail_price ) > 10’ )
and how to modify the search above if both sale_price and retail_price are null?
Or there is better solution ?
MODIFIED :
I implemented it as scope :
public function scopeGetByDoublePrice($query, $price_from= null, $price_to= null)
{
// need to check if sale_price is set then search in sale_price else in retail_price
if ( empty($price_from) and empty($price_to) ) return $query;
if ( !empty($price_from) ) { // $price_from is set
$query->whereNotNull('sale_price')->where('sale_price', '>=', $price_from);
$query->orWhere('retail_price', '>=', $price_from);
} // if (!empty($price_from) ) { // $price_from is set
if ( !empty($price_to) ) { // $price_to is set
$query->whereNotNull('sale_price')->where('sale_price', '<=', $price_to);
$query->orWhere('retail_price', '<=', $price_to);
} // if (!empty($price_to) ) { // $price_to is set
return $query;
}
but setting 2 values 31 and 33 I have different result I expected :
https://imgur.com/a/AYTJAJn
I expected only the first row would be in results set!
In sql-editor I set "()" manually, as :
SELECT sale_price, retail_price
FROM articles
LEFT JOIN brands AS b on b.id = articles.brand_id
LEFT JOIN article_inventories AS ai on ai.article_id = articles.id
WHERE ( ( sale_price is not null AND sale_price >= '31' OR retail_price >= '31' ) AND
( sale_price is not null AND sale_price <= '33' OR retail_price <= '33') )
and it works as I need. If there is a way to set "()" in my scope?
Use to following constraint:
$price = 10;
$builder->where(function($query) use ($price) {
$query->whereNotNull('sale_price')->where('sale_price', '>', $price);
$query->orWhere('retail_price', '>', $price);
});
This will add the following to your query:
AND (sale_price IS NOT NULL and sale_price > 10 OR retail_price > 10)
What's important, you'll find those extra constraints wrapped in parenthesis which will let you avoid the situation, when other constraints are ignored because of the OR.

Get month wise count from Mysql database even if there are no results

I am creating graph for display month wise count from Mysql database.
Execute this following query:
$cash_query = $this->db->query("select COUNT(*) as count_monthwise, MONTH(FROM_UNIXTIME(dt_added)) as month from `order` where user_id='1' and status != '9' and payment_type = '1' GROUP BY month");
$cash_result = $cash_query->result();
Output:
Array
(
[0] => stdClass Object
(
[count_monthwise] => 1
[month] => 8
)
[1] => stdClass Object
(
[count_monthwise] => 2
[month] => 9
)
)
In above output, there are display "count_monthwise" means count and month "8" means "8th month - August".
But i want to display output with all months, if find count are 0 in any months, then display [count_monthwise] => 0.
I want to display Exact output like:
Array
(
[0] => stdClass Object
(
[count_monthwise] => 1
[month] => 1
)
[1] => stdClass Object
(
[count_monthwise] => 1
[month] => 2
)
.
.
.
.
.
.
.
[10] => stdClass Object
(
[count_monthwise] => 0
[month] => 11
)
[11] => stdClass Object
(
[count_monthwise] => 0
[month] => 12
)
)
I have used using foreach loop something like this, but this is not working.
Loop
foreach($cash_result as $cash => $cash_value){
for($i=0;$i<=11;$i++){
if($i == $cash){
}
}
}
That could be the one way around:
SELECT
COALESCE(yourQuery.count_monthwise,0) AS monthwise_count,
allMonths.month
(SELECT 1 AS month UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12 ) AS allMonths
LEFT JOIN
(
SELECT
COUNT(*) as count_monthwise,
MONTH(FROM_UNIXTIME(dt_added)) as month
from `order`
where user_id='1' and status != '9' and payment_type = '1'
GROUP BY month
) AS yourQuery
ON allMonths.month = yourQuery.month
use below way after getting the result from database don't do complex query just do some code twist
$cash_result = $cash_query->result_array(); // make it to array
$month = range(1,12); // month array
$new_array = array();
$counta = count($month);
for($i=0; $i<$counta ; $i++){
foreach($arr as $key=>$row){
if(($month[$i] == $row['month'])){
$new_array[$i] = $arr[$key];
break;
}else{
$new_array[$i] = array('count_monthwise' => 0,'month' => $month[$i]);
}
}
}
echo '<pre>'; print_r($new_array);

symfony2: select from Table where start=today

The "start" is a dateTime. I'm trying to get all rows that have "start" = Today without considering the hours and mins.
This what I did so far.
Only events with this form 'Y-m-d 00:00:00' are selected
$em = $this->getDoctrine()->getManager();
$onthisday = $em->createQuery('
SELECT e
FROM ECMEventBundle:Events e
WHERE e.start = CURRENT_DATE()
AND e.eventcreator = :userId'
)->setParameter ( 'userId', $user->getId () );
$todayEvent = $onthisday->getResult();
Any response will be appreciated.
you can use php DateTime class:
$myDate = new \DateTime();
$em = $this->getDoctrine()->getManager();
$onthisday = $em->createQuery('
SELECT e
FROM ECMEventBundle:Events e
WHERE e.start > :myDate
AND e.eventcreator = :userId'
)->setParameter ( 'userId', $user->getId () )
->setParameter ( 'myDate', $myDate->format('Y-m-d 0:0:0') );

Mysql: How to query with if else condition inside if

I'm getting trouble to query my data. I do not know where to start with query if else condition inside if.
Problem is:
How to query if its type = cpm and end_date < now() then change result value type to before, and if its type = cpm and end_date > now() then change result value type to after.
I have a data in table, result as below :
And I want to get
result as below :
Array(
[0] => Array
(
[id] => 1
[type] => free
[end_date] => 2013-06-20
)
[1] => Array
(
[id] => 4
[type] => after
[end_date] => 2013-08-29
)
[2] => Array
(
[id] => 5
[type] => before
[end_date] => 2013-06-20
)
)
Thanks in advance.
Something like this should work:
select
id,
case
when (type = 'cpm' and end_date < now()) then 'before'
when (type = 'cpm' and end_date > now()) then 'after'
else type
end as type,
end_date
from my_table;
You could use MySQL CASE - http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html#operator_case
CASE
WHEN `type` = 'cpm' AND `end_date` < NOW() THEN 'before'
WHEN `type` = 'cpm' AND `end_date` > NOW() THEN 'after'
ELSE `type`
END as `type`
You can use WHEN .. CASE for this .
Here is Link for your solution SQLfiddle