data from few MySQL tables sorted by ASC - php

In the dbase I 've few tables named as aaa_9xxx, aaa_9yyy, aaa_9zzz. I want to find all data with a specified DATE and show it with the TIME ASC.
First, I must find a tables in the dbase:
$STH_1a = $DBH->query("SELECT table_name
FROM information_schema.tables
WHERE table_name
LIKE 'aaa\_9%'
");
foreach($STH_1a as $row)
{
$table_name_s1[] = $row['table_name'];
}
Second, I must find a data wit a concrete date and show it with TIME ASC:
foreach($table_name_s1 as $table_name_1)
{
$STH_1a2 = $DBH->query("SELECT *
FROM `$table_name_1`
WHERE
date = '2011-11-11'
ORDER BY time ASC
");
while ($row = $STH_1a2->fetch(PDO::FETCH_ASSOC)) {
echo " ".$table_name_1."-".$row['time']."-".$row['ei_name']." <br>";
}
}
.. but it shows the data sorted by tables name, then by TIME ASC. I must to have all this data (from all tables) sorted by TIME ASC.
Thank You dev-null-dweller, Andrew Stubbs and Jaison Erick for your help.
I test the Erick solution :
foreach($STH_1a as $row) {
$stmts[] = sprintf('SELECT *
FROM %s
WHERE date="%s"', $row['table_name'], '2011-11-11');
}
$stmt = implode("\nUNION\n", $stmts);
$stmt .= "\nORDER BY time ASC";
$STH_1a2 = $DBH->query($stmt);
while ($row_1a2 = $STH_1a2->fetch(PDO::FETCH_ASSOC)) {
echo " ".$row['table_name']."-".$row_1a2['time']."-".$row_1a2['ei_name']." <br>";
}
it's working but I've problem with 'table_name' - it's always the LAST table name.
//----------------------------------------------------------------------
...and the ending solution with all fixes, thanks all for your help, :))
foreach($STH_1a as $row) {
$stmts[] = sprintf("SELECT *, '%s' AS table_name
FROM %s
WHERE date='%s'", $row['table_name'], $row['table_name'], '2011-11- 11');
}
$stmt = implode("\nUNION\n", $stmts);
$stmt .= "\nORDER BY time ASC";
$STH_1a2 = $DBH->query($stmt);
while ($row_1a2 = $STH_1a2->fetch(PDO::FETCH_ASSOC)) {
echo " ".$row_1a2['table_name']."-".$row_1a2['time']."-".$row_1a2['ei_name']." <br>";
}

Instead of printing the line as you fetch it from db, gather all data in one array taht you will be able to sort with usort and your own callback function.
Other option is to get it sorted directly from mysql, using UNION selects like this:
$SQL = "
(SELECT '$table_name_1' AS tbl_name, time, ei_name FROM `$table_name_1` WHERE date = '2011-11-11')
UNION
(SELECT '$table_name_2' AS tbl_name, time, ei_name FROM `$table_name_2` WHERE date = '2011-11-11')
UNION
(SELECT '$table_name_3' AS tbl_name, time, ei_name FROM `$table_name_3` WHERE date = '2011-11-11')
ORDER BY time ASC
";

You need to use the UNION sql directive:
<?php
$STH_1a = $DBH->query("SELECT table_name
FROM information_schema.tables
WHERE table_name
LIKE 'aaa\_9%'");
$stmts = array();
foreach($STH_1a as $row)
{
$stmts[] = sprintf('SELECT *, %s AS `table_name` FROM %s WHERE date="%s"', $row['table_name'], $row['table_name'], '2011-01-01');
}
$stmt = implode("\nUNION\n", $stmts);
$stmt .= "\nORDER BY time ASC";
$STH_1a2 = $DBH->query($stmt);
FIX: Included the table name as returned value.

The correct way to fix it will be to UNION your selection data as stated in other answers.
A quick fix would be to change your second code block to something like:
$Sorted = array();
foreach($table_name_s1 as $table_name_1)
{
$STH_1a2 = $DBH->query("SELECT *
FROM `$table_name_1`
WHERE date = '2011-11-11'
ORDER BY time ASC
");
while ($row = $STH_1a2->fetch(PDO::FETCH_ASSOC)) {
$Sorted[$row['time']] = " ".$table_name_1."-".$row['time']."-".$row['ei_name']." <br>";
}
}
ksort($Sorted);
foreach($Sorted as $Entry) {
echo $Entry;
}
Note: This will 'fail' for cases where there are multiple entries for one date.

Related

Add COUNT and DISTINCT in $query

How to add select COUNT and DISTINCT in the below $query? Please let me know if you need any other details to solve this issue. Thank you for your time.
if(isset($_POST["intake_year"]))
{
$query = "
SELECT * FROM marketing_data
WHERE intake_year = '".$_POST["intake_year"]."'
";
$statement = $connect->prepare($query);
$statement->execute();
$result = $statement->fetchAll();
foreach($result as $row)
{
$output[] = array(
'semester' => $row["semester"],
'student_matric' => floatval($row["count"])
);
}
echo json_encode($output);
}
//SELECT count(student_matric) AS count, semester, intake_year FROM marketing_data GROUP BY intake_year - This query is to only COUNT student_matric
//SELECT DISTINCT semester FROM marketing_data ORDER BY semester DESC - This query is to only DISTINCT semester
I guess you are looking for something like that
$query = "
SELECT distinct semester , count(student_matric) as count FROM marketing_data
WHERE intake_year = '".$_POST["intake_year"]."'
Group by student_matric " ;

Identify change in job code from a mySQL table

I am working with a very large table in MySQL containing employee information collected over the last four years. I want to know if someone's job code changed between that time, and if so, push their data into an array for json encoding in php.
An example of the data looks like this:
Year Emp ID Job Code
2015 1234 X908
2014 1234 X908
2013 1234 X908
**2015 5421 Y444**
2014 5421 Z900
2013 5421 Z900
For employee 1234 there has been no job change between 2013-2015; I would however like to catch employee 5421 whose job code changed between 2014 and 2015.
So far, I have written a script in PHP without good results.
$query = mysqli_query("SELECT year, emp_id, job_code from big_table ");
$rows = array();
while ($r = mysql_fetch_assoc($query)) {
if ($r['emp_id'] == $r['emp_id'] and $r['job_code'] != $r['job_code']) {
$rows[] = $r;
}
echo json_encode($rows);
Thank you in advance for your help!
You can get the required data in the SQL query without having to pull all user records into PHP. This will be significantly more efficient than processing the data in PHP.
You can get the job code count for each user:
SELECT emp_id, COUNT(DISTINCT job_code) AS diffjobs FROM big_table GROUP BY emp_id
Then you can conditionally get users with more than 1 distinct job code by wrapping it in a subquery:
SELECT emp_id, diffjobs FROM
(SELECT emp_id, COUNT(DISTINCT job_code) AS diffjobs FROM big_table GROUP BY emp_id) d
WHERE diffjobs > 1
This loop should work:
$rows = array();
$jobChanges = array();
while ($r = mysql_fetch_assoc($query)) {
if (!isset($rows[$r['emp_id']])){
$rows[$r['emp_id']] = $r;
} elseif ($rows[$r['emp_id']]['job_code'] != $r['job_code']) {
// Handle differing job_code...
if (!isset($jobChanges[$r['emp_id'])) {
$jobChanges[$r[emp_id]] = array();
}
// Keep track of all differing job codes per emp_id
// I am not going to go any further than that...
$jobChanges[$r[emp_id]][] = $r;
}
}
You can get the desired employees whose job has changed in between years using GROUP BY and HAVING clause, like this:
$query = mysqli_query($link, "SELECT emp_id from big_table GROUP BY emp_id HAVING COUNT(DISTINCT job_code) > 1");
$rows = array();
while ($r = mysqli_fetch_assoc($query)){
$rows[] = $r;
}
echo json_encode($rows);
Caution: Don't mix mysqli and mysql database extensions in your code.
This can be done with a JOIN query in MySQL, so that you only return the rows that have changed from the previous year -
SELECT
a.year, a.emp_id, a.job_code,
b.year prev_year, b.job_code prev_job_code
FROM big_table a
JOIN big_table b
ON a.emp_id = b.emp_id
AND b.year = a.year-1
WHERE a.job_code != b.job_code
see this SQLFiddle - http://sqlfiddle.com/#!9/95e680/10
so your code could be simplified to -
$query = mysqli_query("SELECT a.year, a.emp_id, a.job_code, b.year prev_year, b.job_code prev_job_code FROM big_table a JOIN big_table b ON a.emp_id = b.emp_id AND b.year = a.year-1 WHERE a.job_code != b.job_code ");
$rows = array();
while ($r = mysqli_fetch_assoc($query)) {
$rows[] = $r;
}
echo json_encode($rows);
note - you had mysqli_query(), but mysql_fetch_assoc(), so I updated to mysqli_fetch_assoc()
If you still wanted to do this in php, you need to save the last row value to a temporary array, and then check if the job_code has changed.
it would look something like this -
$query = mysqli_query("SELECT year, emp_id, job_code from big_table ORDER BY emp_id, year");
$temp = array();
$rows = array();
while ($r = mysqli_fetch_assoc($query)) {
if(!isset($temp[$r['emp_id']]){
$temp[$r['emp_id']] = $r; // add this row to the temp array
}
else {
if ($r['job_code'] != $temp[$r['emp_id']]['job_code']) {
// add the previous values for comparison
$r['prev_year'] = $temp[$r['emp_id']]['year'];
$r['prev_job_code'] = $temp[$r['emp_id']]['job_code'];
// add this row
$rows[] = $r; // add this row
// replace the last temp array with this array
$temp[$r['emp_id']] = $r;
}
}
echo json_encode($rows);
note - I changed the query by adding an ORDER BY -> ORDER BY emp_id, year

Sort query by time and list next entries

I'm trying to sort this query by time.
I have a gaming match system. And I want to get a list of next 5 matches from my local time zone.
<?php
include_once "include/dbcompo.php";
$q=mysqli_query($con, "SELECT * FROM kamper ORDER BY tid LIMIT 5");
while($row = mysqli_fetch_array($q))
{
$clan1 = $row['clan1'];
$clan2 = $row['clan2'];
$server = $row['server'];
$tid = $row['tid'];
echo $clan1." ".$clan2." ".$server." ".$tid;
echo "<br />";
}
?>
Add a WHERE clause in your query: WHERE tid > NOW().
With NOW() you take the time of the server, maybe you should replace it with new DateTime(null)->getTimestamp()
Something like that:
<?php
mysqli_query($con, 'SELECT * FROM kamper WHERE tid > NOW() ORDER BY tid LIMIT 5');
// or
mysqli_query($con, 'SELECT * FROM kamper WHERE tid > '.new DateTime(null)->getTimestamp().' ORDER BY tid LIMIT 5');
?>
Two options:
1st option: Make the time field a numeric field and sort in PHP:
$queryResult = mysqli_query($con, $query);
while($row = mysqli_fetch_array($queryResult) {
$oldArray[$row['time'] = $row;
}
$array = ksort($oldArray);
foreach($array as $time=>$row) {
// do something
}
2nd option: Make a subquery
SELECT * FROM (
SELECT * FROM kamper WHERE timezone = 'UTC' ORDER BY tid
) LIMIT 5

SQL multiple table query with UNION, how to get table names

I have the following table structure. One table EQUITIES and a table for each row in this table.
EQUITIES table:
id instrument
and tables for every instrument with are all similar to this:
Tables named like EE5367126893 (various names and the names are stored in equities table).
EE5367126893
id chg
EDIT:
My code is BAD. It somehow gets me wrong results and i can't seem to find an error.
<?
//CREATION OF TOP MOVERS
include('connect.php');
$sql = "SELECT * FROM equities";
$result = mysql_query($sql) or die(mysql_error());
$instruments = array();
while ($row = mysql_fetch_array($result)) {
array_push($instruments, $row["instrument"]);
}
$i=0;
foreach($instruments as $instrument) {
$sqlx .= "(SELECT id, chg, vol, '$instrument' as name FROM ".$instrument." ORDER BY id DESC LIMIT 1)";
if ($i<count($instruments)-1){
$sqlx .= " UNION ";
$i++;
}
}
$gsql = $sqlx;
$lsql = $sqlx;
$vsql = $sqlx;
//Gainers
$gsql .= " ORDER BY chg DESC LIMIT 3";
$gresult = mysql_query($gsql) or die(mysql_error());
while ($grow = mysql_fetch_array($gresult)) {
$g[$grow['name']] = $grow['chg'];;
}
print_r($g);
//losers
$lsql .= " ORDER BY chg ASC LIMIT 3";
$lresult = mysql_query($lsql) or die(mysql_error());
while ($lrow = mysql_fetch_array($lresult)) {
$l[$lrow['name']] = $lrow['chg'];;
}
print_r($l);
//most volume
$vsql .= " ORDER BY vol DESC LIMIT 3";
$vresult = mysql_query($vsql) or die(mysql_error());
while ($vrow = mysql_fetch_array($vresult)) {
$v[$vrow['name']] = $vrow['vol'];;
}
print_r($v);
?>
It got me results:
Array
(
[LV0057869] => 0.68
[EE310054309] => 0.00
[EE3100034553] => -5.03
)
Array
(
[LV0054359] => -0.84
[LT0000543337] => -3.83
[LT00453127375] => -4.03
)
Array
(
[EE310054334653] => 791
[EE3100003609] => 58538
[LT000543337] => 33240
)
Its pretty obvious that I'm not getting the the highest, lowest or values with most vol (as -0.84>-5.03).It looks like random values got locked with this query. Where's the catch? Im pretty sure theres something bad with my sql query...
You can add name to select
SELECT id, chg, 'table_name or instrument_name' as inst_name from ...
Example:
$sqlx .= "(SELECT id, chg, '$instrument' as name FROM ".$instrument." ORDER BY id DESC LIMIT 1)";
It seems that vol has got VARCHAR type and rows are sorted by chars not by integers.
Could you provide your table scheme?

How can I add array values to a MySQL query?

I'm using the following code to sort MySQL queries into time/date:
mysql_select_db("user_live_now", $con);
$result = mysql_query("SELECT * FROM users_newest_post ORDER BY users_date_post DESC");
while($row = mysql_fetch_array($result))
{
print($row['user']);
}
instead of having the PHP run through and show all the values in the table can I have it show the values from an array?
So, you want to find specific users in the SQL query to return? Build your query programmatically:
$users = array('User1','John','Pete Allport','etc');
$sql = "SELECT * FROM `users_newest_post` WHERE ";
$i = 1;
foreach($users as $user)
{
$sql .= "`username` = '$user'";
if($i != count($users))
{
$sql .= " OR ";
}
$i++;
}
$sql .= " ORDER BY `users_date_post` DESC";
$result = mysql_query($sql);
Which would get you a query like:
SELECT * FROM `users_newest_post`
WHERE `username` = 'User1'
OR `username` = 'John'
OR `username` = 'Pete Allport'
OR `username` = 'etc'
ORDER BY `users_date_post`
DESC
So, you want to find all posts for a certain date or between two dates, kinda hard to do it without knowing the table structure, but you'd do it with something like this:
//Here's how to find all posts for a single date for all users
$date = date('Y-m-d',$timestamp);
//You'd pull the timestamp/date in from a form on another page or where ever
//Like a calendar with links on the days which have posts and pass the day
//selected through $_GET like page.php?date=1302115769
//timestamps are in UNIX timestamp format, such as you'd get from time() or strtotime()
//Note that, without a timestamp parameter passed to date() it uses the current time() instead
$sql = "SELECT * FROM `posts` WHERE `users_date_post` = '$date'"
$results = mysql_query($sql);
while($row = mysql_fetch_assoc($results))
{
echo $row['post_name'] . $row['users_date_post']; //output something from the posts
}
//Here's how to find all posts for a range of dates
$startdate = date('Y-m-d',$starttimestamp);
$enddate = date('Y-m-d',$endtimestamp);
//Yet again, date ranges need to be pulled in from somewhere, like $_GET or a POSTed form.
//Can also just pull in a formatted date rather than a timestamp and use it straight up instead, rather than going through date()
$sql = "SELECT * FROM `posts` WHERE `users_date_post` BETWEEN '$startdate' AND '$enddate'";
//could also do:
//"SELECT * FROM `posts` WHERE `users_date_post` > '$startdate' AND `users_date_post` < '$endate'"
$results = mysql_query($sql);
while($row = mysql_fetch_assoc($results))
{
//output data
}
To find posts for a specific user you would modify the statement to be something like:
$userid = 5; //Pulled in from form or $_GET or whatever
"SELECT * FROM `posts` WHERE `users_date_post` > '$startdate' AND `users_date_post` < '$enddate' AND `userid` = $userid"
To dump the result into an array do the following:
mysql_select_db("user_live_now", $con);
$result = mysql_query("SELECT * FROM users_newest_post ORDER BY users_date_post DESC");
while($row=mysql_fetch_assoc($result))
{
$newarray[]=$row
}
What you probably want to do is this:
$users = array("Pete", "Jon", "Steffi");
$users = array_map("mysql_real_escape_string", $users);
$users = implode(",", $users);
..("SELECT * FROM users_newest_post WHERE FIND_IN_SET(user, '$users')");
The FIND_IN_SET function is a but inefficient for this purpose. But you could transition to an IN clause with a bit more typing if there's a real need.
$sql = 'SELECT * FROM `users_newest_post` WHERE username IN (' . implode(',', $users) . ')';

Categories