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

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

Related

MySQL table order by values from relation table by newest date

Is it possible to select from mySQL table rows ordered by joined table values by current date?
Maybe I show it. I Have two tables:
One country have many scores GROUPED BY date. Is it possible to sort countries by current date scores?
I have countires with scores from table in PHP arrays:
$countries = array(
'England' =>
array('name', 'tag',
'scores' => array(
0 => array('date' => '2018-07', 'score' => 100),
1 => array('date' => '2018-08', 'score' => 50)
)),
'USA' =>
array('name', 'tag',
'scores' => array(
0 => array('date' => '2018-08', 'score' => 50),
1 => array('date' => '2018-09', 'score' => 20)
)
),
'France' =>
array('name', 'tag',
'scores' => array(
0 => array('date' => '2018-08', 'score' => 30),
1 => array('date' => '2018-09', 'score' => 100)
)
)
);
I need to select countries ordered by scores for current date. Lets say current date is 2018-09. I need to search countries and sort them like this:
$countries = array(
'France' =>
array('name', 'tag',
'scores' => array(
0 => array('date' => '2018-08', 'score' => 30),
1 => array('date' => '2018-09', 'score' => 100)
)
),
'USA' =>
array('name', 'tag',
'scores' => array(
0 => array('date' => '2018-08', 'score' => 50),
1 => array('date' => '2018-09', 'score' => 20)
)
),
'England' =>
array('name', 'tag',
'scores' => array(
0 => array('date' => '2018-07', 'score' => 100),
1 => array('date' => '2018-08', 'score' => 50)
)),
);
England is last becouse havent scores for date '2018-09'
Second is France becouse for date '2018-09' have 100 points
USA is last becosue for date '2018-09' have 20 points
SELECT c.name, s.date, s.score FROM country c LEFT JOIN score s ON s.country_id=c.id GROUP BY date ORDER BY (??)
We could do something like this, to get the latest score date for each country_id, along with the score for that latest date, and then order by those values:
SELECT c.name
, s.date
, s.score
FROM country c
LEFT
JOIN score s
ON s.country_id = c.id
LEFT
JOIN ( SELECT m.country_id
, MAX(m.date) AS max_date
FROM score m
GROUP
BY m.country_id
) n
ON n.country_id = c.id
LEFT
JOIN score o
ON o.country_id = n.country_id
AND o.date = n.max_date
ORDER
BY o.date DESC
, o.score DESC
, c.name ASC
, s.date ASC
Note that this assumes that the (country_id,date) tuple is unique in the score table. If we don't have that guarantee, we can tweak the query to accommodate that. Something like this:
SELECT c.name
, s.date
, s.score
FROM country c
LEFT
JOIN score s
ON s.country_id = c.id
LEFT
JOIN ( SELECT o.country_id
, o.date
, MAX(o.score) AS max_date_score
FROM ( SELECT m.country_id
, MAX(m.date) AS max_date
FROM score m
GROUP
BY m.country_id
) n
JOIN score o
ON o.country_id = n.country_id
AND o.date = n.max_date
GROUP
BY o.country_id
, o.date
) p
ON p.country_id = c.id
ORDER
BY p.date DESC
, p.max_date_score DESC
, c.name ASC
, s.date ASC
, s.score DESC

how to combine 2 sql queries to get 1 result

SELECT users.name, users.registrationdate, users.city, users.status
FROM users, referrals
WHERE users.username= referrals.referrals AND referrals.username='user_name'
SELECT adearning, reffearning
FROM earnings WHERE usersname='user_name33'
How can I combine these two queries as if first query condition doesn't match and doesn't run.. then the second query should run and return some value if condition match
Try this
$query1 = $this->db->query("SELECT users.name, users.registrationdate, users.city, users.status
FROM users, referrals
WHERE users.username = referrals.referrals AND referrals.username='user_name'")
$result1 = $query1->result_array();
$query2 = $this->db->query("SELECT adearning, reffearning FROM earnings WHERE usersname='user_name33' ")
$result2 = $query2->result_array();
$dataArray = array_merge($result1, $result2);
if want to check the result, end of the line add this
print_r($dataArray);die;
On this it will print all of them in one array
Example
$result1 = array(
'0' => 'sjhccsd',
'1' => 'ddd',
'2' => 'df',
'3' => 'dfd',
);
$result2 = array(
'0' => 'sjhccsd',
'1' => 'ddd',
'2' => 'df',
'3' => 'dfd',
);
$dataArray = array_merge($result1, $result2);
print_r($dataArray);
Output : Array ( [0] => sjhccsd [1] => ddd [2] => df [3] => dfd [4] => sjhccsd [5] => ddd [6] => df [7] => dfd )

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);

unread count and grouping

I have a very similar setup to this answer Is there a simpler way to achieve this style of user messaging?
However I'm having an issue with getting the total unread conversations and not unread messages.
SELECT p.conversation_id, COUNT(p.conversation_id) as unread
FROM participation AS p
INNER JOIN messages AS m
ON m.conversation_id = p.conversation_id AND m.seen = 0
WHERE p.uid1 = {$user->data['id']}
GROUP BY m.conversation_id`
I'm only selecting p.conversation_id for testing purposes, but the result I am getting is:
Array
(
[conversation_id] => 1
[unread] => 77
)
If I were to put the results in a PHP while loop I get
Array
(
[conversation_id] => 1
[unread] => 77
)
Array
(
[conversation_id] => 3
[unread] => 7
)
Array
(
[conversation_id] => 8
[unread] => 1
)
Array
(
[conversation_id] => 17
[unread] => 35
)
Array
(
[conversation_id] => 22
[unread] => 2
)
Array
(
[conversation_id] => 24
[unread] => 305
)
Array
(
[conversation_id] => 29
[unread] => 41
)
Array
(
[conversation_id] => 31
[unread] => 1
)
The result I am wanting is unread: 8
I think you just want conditional aggregation:
SELECT p.conversation_id,
SUM(m.seen = 0) as unseen,
SUM(m.seen <> 0) as seen
FROM participation AS p INNER JOIN
messages AS m
ON m.conversation_id = p.conversation_id AND m.seen = 0
WHERE p.uid1 = {$user->data['id']}
GROUP BY m.conversation_id
In addition, if you want the total over all conversations, leave out the group by.

SQL, MySQL and php

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