I have two separate calendars: reservation_schedule and maintenance_schedule calendars. Reservation_schedule fetch data from reservation table and maintenance_schedule fetch data from maintenance table. My goal is to put both fetched data from the two calendars into one calendar.
Here is the query I used for the reservation_schedule:
SELECT acode
FROM reservation
WHERE month(etd) = '".$month."'
AND dayofmonth(etd) = '".$dayArray["mday"]."'
AND year(etd) = '".$year."'
ORDER BY etd
And for the maintenance_schedule:
SELECT DISTINCT s.reg AS 'reg',
a.date AS 'date'
FROM (SELECT Curdate()
+ INTERVAL (a.a + (10 * b.a) + (100 * c.a)) day AS Date
FROM (SELECT 0 AS a
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9) AS a
CROSS JOIN (SELECT 0 AS a
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9) AS b
CROSS JOIN (SELECT 0 AS a
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9) AS c) a
INNER JOIN maintenance_sched s
ON a.date >= s.date_from
AND a.date <= s.date_to
WHERE Month(date) = '".$month."'
AND Dayofmonth(date) = '".$dayArray["mday"]."'
AND Year(date) = '".$year."'
I can show data from both of them by using UNION but I want the data from the maintenance table to be outputted as string with strikethrough. I'm outputting the query result in this code:
$chkEvent_res = mysql_query($chkEvent_sql) or die(mysql_error());
if (mysql_num_rows($chkEvent_res) > 0) {
$event_title = "<br/>";
while ($ev = mysql_fetch_array($chkEvent_res)) {
$event_title .= stripslashes($ev["reg"])."<br/>";
//$event_title .= "<del>".stripslashes($ev["acode"])."</del><br/>";
}
mysql_free_result($chkEvent_res);
} else {
$event_title = "";
}
If I use the query with UNION, I can't set the output string from maintenance to have strikethrough since it runs the query once. How can I achieve having the fetched data from maintenance table to output with strikethrough? Should I go for the one query with UNION? If I do, how can I separate the data coming from maintenance table and reservation table? If I go with separating the query, how can I run it? Should it be something like $chkEvent_res = mysql_query($chkEvent_sql1) and mysql_query($chkEvent_sql2) or die(mysql_error());? Please help, thanks.
The only way you can UNION these 2 queries is if you have the same number of columns in each query, and each column have the same data type. Not sure about the data types involved -- you have "acode" being returned from the first query and "reg" and "date" from the second query.
Assuming you could actually UNION your results and get what you need, you could consider adding an additional column to your results, returning the source of the query:
SELECT Field1, Field2, Field3, 'Table1' Source
FROM TABLE1
...
UNION
SELECT Field1, Field2, Field3, 'Table2' Source
FROM Table2
...
The you could use that Source column to format your results accordingly.
Here's some additional information about using UNION:
http://dev.mysql.com/doc/refman/5.0/en/union.html
Related
Hello i have mysql table which named numbers like this;
ID
Number
1
3002
2
3004
2000
7545
When i need to insert a new data products table i have to find first number which is not on this table between(3000 to 35000). I mean i need to find first number between this numbers not on numbers table. How can i find it?
$statement = $con->prepare("SELECT * FROM numbers");
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
foreach($result as $row)
{
$arr1[] = $row['numbers'];
}
$arr2 = range(3000,35000);
$missing_numbers = array_diff($arr2,$arr1);
print_r($missing_numbers);
i tried array_diff but i gives results with different keys. When i write $missing_numbers[0] i want to see first missing number.
If you just want the first missing number, it may be easier to read the rows in number order and check for the first one which isn't in the sequence you are after. So a query (with the start and end points as parameters) order by the number and a counter which is what it's expecting to get on each row...
$startPoint = 3000;
$endPoint = 35000;
$statement = $db->prepare("SELECT number
FROM numbers
WHERE number >= :start
and number <= :end
order by number");
$statement->execute([
'start' => $startPoint,
'end' => $endPoint
]);
$expected = $startPoint;
while ($row = $statement->fetch()) {
if ( $row['number'] != $expected ) {
echo "Missing=" . $expected;
break;
}
$expected++;
}
I think your solution will work only thing missing is reordering of the indexes which can be done by using the array_values() function. Update your last lines of code as -
$missing_numbers = array_values(array_diff($arr2,$arr1));
print_r($missing_numbers);
so on printing $missing_numbers[0] you should get the first missing number.
Easy, just need reset keys after array_diff:
...
$missing_numbers = array_values(missing_numbers);
print_r($missing_numbers);
IF you want do it only by using MySQL query and later get the result in PHP you need to do something like this :
Create temporray table with your example :
create table test123(id integer, Number varchar(100))
#insert into test123 (ID, Number) values (1, '3002');
#insert into test123 (ID, Number) values (2, '3004');
#insert into test123 (ID, Number) values (2000, '7545');
CREATE TEMPORARY TABLE WITH RANGE 3000 - 35000
CREATE TEMPORARY TABLE IF NOT EXISTS tableTest AS (
SELECT #row := #row + 1 AS row FROM
(select 0 union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t,
(select 0 union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t2,
(select 0 union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t3,
(select 0 union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t4,
(select 0 union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) t5,
(SELECT #row:=3000) numbers WHERE #row < 35000
)
AND FINALLY you can just select numbers that's not inside your table with data
select * from tableTest t where t.row not in ( select Number from test123)
The output will be select all numbers as you wanted.
I have the following details in MySQL as
user_id follow_user_id
1 2,3,3,3,3
5 1,2,3,3,3,3
6 1,2,3,3,3,3
i write the following code to get the unique code as follow:
SELECT LENGTH( follow_user_id ) - LENGTH( REPLACE( follow_user_id, ',', '' ) ) +1 AS no_of_follow FROM follow WHERE user_id =1;
But it provide the result:6
I need exactly unique rows: i.e:4
Apart from DB design questions you could use in PHP after fetching the row to $result:
count(array_unique(explode(",",$result["follow_user_id")));
$query="SELECT follow_user_id FROM follow WHERE user_id ='".$_POST['user_id']."' "; $query_run=mysql_query($query); $row= mysql_fetch_assoc($query_run);
$count= count(array_unique(explode(",",$row['follow_user_id'])));
$count;
This is better and faster ;)
count(array_flip(explode(",", $result["follow_user_id")));
Or doing it in SQL:-
SELECT COUNT(DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(follow_user_id, ',', units.i + tens.i * 10), ',', -1) AS col1)
FROM sometable
CROSS JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9)units
CROSS JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9)tens
WHERE user_id = 1
(copes with up to 100 comma separated values).
But this would be so much easier with a properly normalised database design
Following up my question where I used the answer to generate data on my calendar called maintenance calendar showing the aircraft's maintenance schedule. This is the MySQL query for it:
SELECT DISTINCT s.reg AS 'reg',
a.date AS 'date'
FROM (SELECT Curdate()
+ INTERVAL (a.a + (10 * b.a) + (100 * c.a)) day AS Date
FROM (SELECT 0 AS a
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9) AS a
CROSS JOIN (SELECT 0 AS a
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9) AS b
CROSS JOIN (SELECT 0 AS a
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9) AS c) a
INNER JOIN maintenance_sched s
ON a.date >= s.date_from
AND a.date <= s.date_to
WHERE Month(date) = '".$month."'
AND Dayofmonth(date) = '".$dayArray["mday"]."'
AND Year(date) = '".$year."'
Here is the maintenance_sched database:
And the calendar looks like this (based on the data from maintenance_sched):
Then, I have another calendar called reservation calendar with the same code as the maintenance calendar though with different query. This is the reservation calendar query: SELECT acode FROM reservation WHERE month(etd) = '".$month."' AND dayofmonth(etd) = '".$dayArray["mday"]."' AND year(etd) = '".$year."' ORDER BY etd".
The reservation table is this:
And the reservation calendar looks like this:
EDIT:
What I want to do is: have these two calendar in one calendar with the result of maintenance_sched query outputted as string with strikethrough. But I can't seem to make the two queries work out together as one.
I do think the answer to this question is to simply join the two queries. An example of this might be like below where you just null out any columns that aren't in your second table.
SELECT id, date, field3, description
FROM table1
UNION
SELECT id, date, field3, null
FROM table2
As there is no relationship among both the table we cannot go for joins, it would be better to go for UNION to combine the result.
This query uses group_concat so will generate common results in following form
2013-03-15 | RP-C1728, RP-C1086
2013-03-08 | RP-C1728, RP-C1086, RP-C143
If you dont want record in this format then just remove group_concat, group by clause from the query.
Query
SELECT a.date, group_concat(a.reg)
FROM
(SELECT DISTINCT s.reg AS 'reg',
a.date AS 'date'
FROM (SELECT Curdate()
+ INTERVAL (a.a + (10 * b.a) + (100 * c.a)) day AS Date
FROM (SELECT 0 AS a
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9) AS a
CROSS JOIN (SELECT 0 AS a
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9) AS b
CROSS JOIN (SELECT 0 AS a
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9) AS c) a
INNER JOIN maintenance_sched s
ON a.date >= s.date_from
AND a.date <= s.date_to
WHERE Month(date) = '".$month."'
AND Dayofmonth(date) = '".$dayArray["mday"]."'
AND Year(date) = '".$year."'
UNION ALL
SELECT acode as 'reg', date as 'date' //Add the date logic here as per your need
FROM reservation
WHERE month(etd) = '".$month."' AND
dayofmonth(etd) = '".$dayArray["mday"]."' AND
year(etd) = '".$year."' ORDER BY etd) a
GROUP BY a.date;
NOTE For the second query add the according date logic
I am creating a line graph in flot, I have it all working except for the days which do not have a result I need them to come back with a result 0 + date. Is this possible in mysql? Here is my current query:
$chartQuery = "SELECT count(date) as counted_leads, UNIX_TIMESTAMP(date) as time FROM enquiries WHERE visibility != 'deleted' group by date";
Or would I need to do it in my php? Here is my code:
<?php
$last_key = end(array_keys($chartResults));
foreach ($chartResults as $item => $value)
{
$timestamp = round($value['time'] * 1000);
if ($item == $last_key)
{
// last element
echo '['.$timestamp.', '.htmlentities($value['counted_leads']).']';
}
else
{
// not last element
echo '['.$timestamp.', '.htmlentities($value['counted_leads']).'],';
}
}
unset($value);
?>
SELECT
ifnull(count(date),0) as counted_leads,
UNIX_TIMESTAMP(date) as time
FROM enquiries WHERE visibility != 'deleted'
group by date
Use if null for defult value
I think this is what you are looking for:
SELECT time, SUM(counted_leads) AS counted_leads
FROM(
SELECT UNIX_TIMESTAMP(date) AS time, count(1) AS counted_leads
FROM enquiries
WHERE visibility != 'deleted'
GROUP BY time
UNION ALL
SELECT a.Date AS time, 0 AS counted_leads
FROM (
SELECT CURDATE() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY AS Date
FROM (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS a
CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS b
CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS c
) a
WHERE a.Date BETWEEN (SELECT MIN(date) FROM enquiries) AND (SELECT MAX(date) FROM enquiries)
) a
GROUP BY time;
I want to count the number of posts for each day to create a graph. My problem is that since SQL doesn't find results for some days (Count is 0), I'm missing rows I need for the chart (since I do want to show days with no posts).
SELECT DATE(Date) AS Day, COUNT(*) AS COUNT
FROM `Posts`
GROUP By `Day`
ORDER BY Date DESC
while($row = mysql_fetch_array($result)) {
echo $row['Date'] . ": " . $row['Count'];
}
Since the loop doesn't display days with 0 results, if on wednesday there are no posts I get: monday-17-3: 5, tuesday-18-3: 2, thursday-20-3: 3. Instead I want to fill out the blanks so I get something like: wednesday-19-3: 0.
How can I echo the days with no results in the loop?
You can work around this by a table of dates, performing an OUTER JOIN, and then performing the grouping. This will provide you with the dates in between (Disclaimer: I'm assuming your dates are in the format YYYY-MM-DD, otherwise you may need to tweak the JOIN statement slightly.).
SELECT A.Date AS Day, COUNT(Posts.Date) AS COUNT
FROM
(
select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) A
LEFT OUTER JOIN `Posts` ON A.Date = `Posts`.`Date`
WHERE A.Date >= DATE_ADD(CURDATE(), INTERVAL -15 DAY)
GROUP BY A.Date
For the date table, I'm using the method from the following post: generate days from date range
Use a loop to go through successive dates, using a function like:
$date = strtotime(date("Y-m-d", strtotime($date)) . " +1 day");
For each cycle, apply your query result. Then you'll have all the dates.