I would like to have two separate queries. The first query I would like to display a bunch of numbers in descending order in a table (pretty simple to do). Then what I would like to do is a second query which for each of those matching numbers I would like to display the corresponding data. The reason I want to do it separately instead of just combing it all into one query is so that I can display all of the results of the first query whether it has data or not. IE:
1 - (blank)
2 - I have data
3 - I also have data
4 - (blank)
5 - I have more data
So far the code I am using is:
// Perform number query
$number_query = mysqli_query($con,$num_query);
while($numbers = mysqli_fetch_array($number_query)) {
// Do data query
$data_query = mysqli_query($con,$d_query);
while($data = mysqli_fetch_array($data_query)) {
if ($numbers['number'] == $data['number']) {
echo $numbers['number'];
echo $data['content'];
echo '<br>';
}
else {
echo $numbers['number'];
echo '<br>';
}
}
}
I dont think I'm taking the right approach but it does seem that I am getting partially the right results as it is displaying the data next to the numbers with content. The problem is that for each piece of data in the database the $numbers['number'] is being replicated. So if $data['content'] has 5 database entries then each entry of the $numbers['number'] is being replicated 5 times.
-------Edit-----
Ok I realized why my question wasnt making sense (maybe). I'm going to use an example of these tables:
Table 1
unique_id | number | identifier | etc
Database Table 1 might be updated once a month, and all the numbers and identifiers must be visible on the page at all times. The query needs to be kept separate because it is used multiple times (more then 10) on other pages so I've included it outside of the page in a header file.
Table 2
unique_id | number | description | etc.
Database Table 2 needs to be referenced via the number columns, this content is changing on an interval of about every 10-15 minutes, now Table 1 might only have 50 rows of data while Table 2 probably has close to a 100+ new rows a day. The query is embedded on the page because it will be the only page that actually uses this specific query.
The idea with the layout is something like this:
<table>
<tr>
<td>Number & Identifier</td> (taken from Table 1)
<td>Description</td> (content from table 2)
<td>(more content from table 2)</td>
etc
So looking back at the top with my question is the problem is that for every description and other content that is being displayed on the page with the corresponding number and identifier information, all the number and identifiers without descriptions or content are being replicated the same amount of times as there are entries with descriptions and content.
If I remove the else conditional statement then the issue becomes that the blank entries do not display at all, which doesnt meet my requirements. The reason that these blank entries need to be in there is that this page can be printed off, so people not using computers can fill out the blank fields with pen/pencil and it can be manually entered in after the fact.
I do understand your question now, but i still think that the solution using join as i posted earlier is your best bet.
http://www.sqlfiddle.com/#!2/26854/2
Related
I have a PHP - MySQL set up . I have a table devicevalue structure of it is like this
devId | vals | date | time
xysz | 23 | 2020.02.17 | 22.06
abcs | 44 | 2020.02.31 | 22.07
The vals columns hold temperature values .
any user loggin in on my webapp have access to only certain devices.
Here are steps
On my website "a user" selects from and to dates for which he wants to see data & submit it
Then these dates are passed a page "getrecords.php " ,where there are lot select queries ( and many are in loop ) to fetch filtered data in required format
The problem is that this table holds almost 2-3 Million records . and in every where clause I have to add to and from conditions. this causes to search in entire table .
My question is there any way that I can get temporary table at step 1 which will have only certain rows based on given two dates and then all my queries on other page will be against that temporary table ?
Edit: If your date column is a text string, you must convert it to a column of type DATE or TIMESTAMP, or you will never get good performance from this table. A vast amount of optimization code is in the MySQL server to make handling of time/date data types efficient. If you store dates or times as strings, you defeat all that optimization code.
Then, put an index on your date column like this.
CREATE INDEX date_from_to ON devicevalue (`date`, devId, vals, `time` );
It's called a covering index because the entire query can be satisfied using it only.
Then, in your queries use
WHERE date >= <<<fromdate>>>
AND date < <<<todate>> + INTERVAL 1 DAY
Doing this indexing correctly gets rid of the need to create temp tables.
If your query has something like `WHERE devId = <<>> in it, you need this index instead (or in addition).
CREATE INDEX date_id_from_to ON devicevalue (devId, `date`, vals, `time` );
If you get a chance to change this table's layout, combine the date and time columns into a single column with TIMESTAMP data type. The WHERE clauses I showed you above will still work correctly if you do that. And everything will be just as fast.
SQL is made to solve your kind of problem simply and fast. With a good data choices and proper indexing, a few million records is a modestly-sized table.
Short answer: No. Don't design temp tables that need to live between sessions.
Longer answer:
Build into your app that the date range will be passed from one page to the next, then use those as initial values in the <form> <input type=text...>
Then make sure you have a good composite index for the likely queries. But, to do that, you must get a feel for what might be requested. You will probably need a small number of multi-column indexes.
You can probably build a SELECT from the form entries. I rarely need to use more than one query, but it is mostly "constructed" on the fly based on the form.
It is rarely a good idea to have separate columns for date and time. It makes it very difficult, for example, to say noon one day to noon the next day. Combine into a DATETIME or TIMESTAMP.
O.Jones has said a lot of things that I would normally add here.
I am in the position where I need to remove records form a dataprovider. Long story shot, I have encrypted data in my db that is decrypted using the afterfind method. I need to ensure the decrypted string is 20 characters long and show the result in a cgrid view.
I have tried the visible option, but this hides the data on a per column basis. I have tried the rowCssClassExpression which successfully hides the rows on the screen using display:none, however, it still shows 1 of 1200 results even though only 10 match and also page 1 has one result, page 2 no results, page 3 2 results etc.
Currently I am able to get this working by doing a cdbcommand queryAll and then looping through and calling the object like so:
foreach($data as $key=>$d)
{
$lengthCheck = Data::model()->findByPk($d['id'])->checkLength;
if($lengthCheck !== true)
{
unset($data[$key]);
}
etc.
I can then use the resulting array in an arrayDataProvider, so effectively I can get the information I need using this methods, however, It is taking over 2 seconds per record, so effectively this would be over 3 minutes for 100 records.
Does anyone have an idea of how I could do this in a smarter/faster way?
I'm trying to figure out how to select the last 5 rows of a table to display on a home screen when there might be gaps in the ids. The database this is for has 1,000s of rows and I don't want to have to call all of them to take the last 5 every time I go to my app's home screen. The problem is that rows sometimes are deleted in the database for various reasons so, for example, if the last row's id is 4023 the second to last row's id might be 4020, so I can't just use the length and count backwards. Ideally it would work like
$get_5_rows = DB::table('rows')->take(5)->get();
Except that instead of collecting the first 5 rows that it would take the last 5.
Thank y'all so much for the help! Any and all help is greatly appreciated!
You may try this:
$rows = DB::table('rows')->orderBy('id', 'desc')->take(5)->get();
You may also use orderBy('created_at') if that field is available. Another similar answer here.
Good day everyone
I have a printing problem so I'm going to explain the problem and share some basic code but the coding is not the problem, the problem is that I'm using the wrong method there must be a better method.
My web page is generated by using PhP to fetch information from mySQL and display each set of information as a table. so I may have 3 tables on 1 page or 100 tables. the problem is I really need to print this but when I do google puts the page breaks straight through my table.
the tables vary in height depending on how much information I need to display.
I use javascript to set the print area.
below you will see I try anticipate the page break with table 3 but when table 1 and 2 take more than a page, it puts the break through table 2 then the rest of page 2 is empty and table 3 is only found on page 3. In this case i would need it to put the break before table 2 so the whole table prints on page 2.
<div id='print_area'>
<table>
this is table 1
</table>
<table>
this is table 2
</table>
<table style='page-break-before:always'>
this is table 3
</table>
</div>
Sorry I need to leave for the day but I'm really hoping some one will be able to help with this problem. I will be checking back tomorrow.
Thank you in advance!
You'll never really be able to guarantee page layout just using PHP and HTML. Have you considered creating a PDF instead of a printable web page? There are very simple but powerful PDF libraries available for PHP, my preferred one is FPDF.
Count the number of rows in each table before you actually print them. Assume a number of rows that fit on a page, and space you need for table headers/space between tables.
So for example
$rows_between_tables=3
$rows_needed_for_header=2
$rows_used_on_this_page=0
$rows_per_page=72 # (depends on font size etc.)
while (there_is_another_table_to_print()) {
$rows_after_this_table = $rows_used_on_this_page +
$rows_needed_for_header + $rows_between_tables +
rows_for_next_table()
if ($rows_after_this_table > $rows_per_page) {
$rows_used_on_this_page=$rows_needed_for_header + rows_for_next_table()
print_next_table_with_page_break_in_front_of_it();
}
else {
$rows_used_on_this_page=$rows_after_this_table;
print_next_table_no_page_break();
}
}
Problem : Data supplied is not ok for me to handle directly.
Description : I'm using curl to get data I need from another website.
However the data supplied on this website is formatted in a way that I need to split it to be able to work with it.
Example:
I'm scraping a div (soccer competition), but the match is supplied in one field, I need to have the 2 teams separated into 2 fields.
MysqlDB Field holds after the scrape:
team 1 - team 2
I need to separate that DB info into 2 columns
preg_match would be able to do this, but there are many opponents, so its a hassle like this.
Right now, I added (manually which is a pain) a team_id column and added myteam to the games which involve my team to the db table and did a where team_id = myteam
This way I can at least sort the competition table and just get my teams games.
This is the data I'm talking about getting with curl:
$value['Wedstrijd'] = htmlentities($value['Wedstrijd'], ENT_QUOTES);
So right now I'm scraping the field and putting it in the db.
I'm wondering, how can I separate the content of $value['Wedstrijd'] into 2 writes.....
Is this even possible?
I'm not able to post the entire code here, the formatting gets screwed.
Using substr and strrpos I was able to get the first team out the field,
I thought setting it to -1 would give me the other way around, which it actually does, but it doesn't go back till the - symbol, it just gives me 1 letter/symbol then.
substr($wedstrijd,0,strrpos($wedstrijd,'-')); this would return the first team, but I'm not sure how to use this to get the team after the - symbol.
use strpos + substr or preg_match