asking about data base - php

function main2(){
$sql = mysql_query("select * from clubs,venue where id<>".$_SESSION['userid']);
$cnt = 0;
while($row = mysql_fetch_array($sql)like
<td width="19%"><?php echo $row['club_name'];?></td>
when I use this code, my entry will be double show to me. What wrong with this like club name will be show twice to me.

Probably because you don't JOIN the tables in your SQL query so the engine doesn't know how the data are related.

You're doing a JOIN on the clubs and venue table. Depending on how your rows are saved, it'll give you all the possible matches. If you have a specific result in mind, please explain it and we'll need your database schema (the structure of your DB) as well.

Related

Codeigniter check if one columns items present in another column

I have been trying to figure out how to check if any of one column's items present in another column in Codeigniter....
I have Bike,Car,Bus in a column(Vehicles) in a table1...
I also have Bus,Helicopter,Ship,Car in a column(Interested) in table2..
How to check if any of table2 interested column's items present in table1 vehicles column...
I tried like this...
$query = $this->db->get('table2');
foreach($query->result() as $row)
{
$a = explode(',', $row->interested);
$this->db->where_in('Vehicles', $a);
$query = $this->db->get('table1');
foreach($query->result() as $row2)
{
echo $row2->ID;
}
}
Could it be done ?? Please Help me... Thanks in advance....
It is very hard to help you without seeing the tables and how you are relating one to the other (such as user_id).
What you should do is two queries. One query to get the data from table 1 of the vehicles you are interested in. Then run through the result set and create a simple array of those vehicles in php. Then do a second query using where_in to select all the rows that are in the chosen vehicles array.
Your method is bad because the number of db queries depends on the size of the result set of your first query. You might find your code trying to do hundreds of database queries.
If you show a diagram of your tables, I could write some example code for you.
Here are the docs for where_in: https://www.codeigniter.com/user_guide/database/query_builder.html#CI_DB_query_builder::where_in

Column 'code' in where clause is ambigous

I need a bit help with a query. I want extract the content from three different table, this table have different records so the code key is different agains the other table. The table contains the credentials for the login, I need to check if the code and the email is found in almost one table, this is an example:
$Query = "SELECT * FROM login_tb1, login_tb2, login_tb3
WHERE (code = '".mysql_real_escape_string($code)."') OR
(email = '".mysql_real_escape_string($email)."') ";
Now when I execute this query I get this error:
Column 'code' in where clause is ambigous
I can't perform a JOIN 'cause the column code is different, all the records are different. All the table have the same structure anyway. How can I fix this?
Thanks.
It took me a while to understand that error message as well. Ambigous is such a fancy word. In human language, it means that MySQL is trying to tell you: "Hey man, the column exists in multiple tables in the select clause, so I don't know which table you mean!". You should be explicit about the table:
$Query = "SELECT * FROM login_tb1, login_tb2, login_tb3
WHERE (login_tb1.code = '".mysql_real_escape_string($code)."') OR
(login_tb1.email = '".mysql_real_escape_string($email)."') ";
If you don't care about which table and they have the same schema, you still need to be explicit, so your query will be a bit more advanced:
SELECT * FROM login_tb1 as l1, login_tb2 as l2, login_tb3 as l3
WHERE ( l1.code = 'code' OR l1.email = 'email' )
OR ( l2.code = 'code' OR l2.email = 'email' )
OR ( l3.code = 'code' OR l3.email = 'email' )
Side note: I don't know your exact use case, but it seems a bit like an anti-pattern that you have multiple login tables with the seemingly same schema. Unless you have a very specific reason not to, you should keep it in a single table.
Code column would be part of more than one table.
in this case prefix with anyone of the table..
e.g login_tb1.code
this would do the trick
You need to tell mysql which code column to use.
Apparently, that column appears in more than one table, so for each table you want to check the code column, write it like this:
tablename.code
This way mysql will know which column to use
I also suggest taking a look at your ta le structure, since having 3 tables with the same structure seems weird.
You can post a question a out the as well or elaborate.
There are similar columns in the tables. You need to properly alias the table
$Query = "SELECT t1.col,t2.col,t3.col FROM login_tb1 as t1,
login_tb2 as t2, login_tb3 as t3
WHERE (t1.code = '".mysql_real_escape_string($code)."') OR
(t2.email = '".mysql_real_escape_string($email)."') ";

Can I run a single SELECT rather than two nested to link two tables, omitting dupes, and return value if they match? MySQL / PHP

total n00b here, first post, so please be constructive! I've bought a book to teach myself PHP / MySQL - and not one which is universally praised, unfortunately - so my progress is a bit erratic.
I have two tables which I want to link. I want to display all of the information held in table 1 (let's call it Records), but ONLY once. I then want to check whether each item in Records has a match to a specific field in table 2 (UserTable) and if it does, display a ticked checkbox, or an empty checkbox if there's no match.
The issues I've had to date are only displaying the items from Records where there's a match, or displaying multiple instances of each item in Records where there are multiple matches. I've solved these with the code below - but I keep thinking there must be a better way to do this, perhaps with a single link?
Anyway, here are some excerpts from the code:
$sql = "SELECT * FROM Records";
$res = mysqli_query($mysqli,$sql);
while ($iteminfo = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
$recordid2 = $iteminfo['record_id'];
I've omitted a section which pulls out the relevant data from Records and starts to build a table, then:
$sql2 = "SELECT COUNT(*) AS matches FROM UserTable
where usertable.item = '$recordid2' and User_ID = '$current_user_id'";
$res2 = mysqli_query($mysqli, $sql2);
$matches = mysqli_fetch_array($res2, MYSQLI_ASSOC);
$matches2 = $matches['matches'];
if ($matches2) {
$output = "<input type='checkbox' name='test' checked>"; } else {
$output = "<input type='checkbox' name='test'>";
As I say, this works, but it feels a bit clumsy - I'm running a separate nested query for every item in Records, which over time could become really slow. Is there a way to run a single query for the whole which brings through all of the row info (once) and a 0 or 1 depending on whether there is a match in UserTable? I've tried using DISTINCT but couldn't get it to work.
How about this:
SELECT * FROM Records
LEFT JOIN (
SELECT usertable.item, COUNT(User_ID) AS matches FROM UserTable
WHERE User_ID = '$current_user_id'
GROUP BY usertable.item
) as UserTable ON record_id = usertable.item
This fetches ALL records, and also only the matching rows for the given User ID in UserTable (change the User ID to fetch details for a different user).
If a row in Record exists, but no matching row exists in UserTable, then "matches" will be NULL. Otherwise it should be a numeric value greater than zero.
Just run this in PHP to handle the checkbox stuff. (it checks for matches greater than zero, and only if found, will print out the "checked" attribute)
<input type="checkbox" name="test" <?=((int)$record['matches'] > 0) ? 'checked="checked"' : ''; ?> />
Well done for noticing that the approach is clumsy. Take some time to look at the SQL language and better understand it. In particular you want to learn how to JOIN. Probably an INNER JOIN. Other types are FULL OUTER JOIN, LEFT OUTER JOIN and RIGHT OUTER JOIN.
I suggest that rather than doing the joining in the procedural code you do it in the SQL. Then make a single call to the DB, e.g.
select records.field1, records.field2, matches.field1, matches.field2
from records
, matches
where records.field = matches.field;
Play with this query until you get the results you want then call this from PHP
$sql = <query from above>
$res = mysqli_query($mysqli,$sql);
One good thing about this is that the SQL language is fairly transferable. Everything form Access to Oracle uses a similar syntax. And you can use this knowledge regardless of the procedural language you're working with (PHP, .NET, etc)
Good luck.

Sorting by ratings in a database - Where to put this SQL? (PHP/MySQL)

OK - I'll get straight to the point - here's the PHP code in question:
<h2>Highest Rated:</h2>
<?php
// Our query base
$query = $this->db->query("SELECT * FROM code ORDER BY rating DESC");
foreach($query->result() as $row) {
?>
<h3><?php echo $row->title." ID: ";echo $row->id; ?></h3>
<p class="author"><?php $query2 = $this->db->query("SELECT email FROM users WHERE id = ".$row->author);
echo $query2->row('email');?></p>
<?php echo ($this->bbcode->Parse($row->code)); ?>
<?php } ?>
Sorry it's a bit messy, it's still a draft. Anyway, I researched ways to use a Ratings system - previously I had a single 'rating' field as you can see by SELECT * FROM code ORDER BY rating DESC. However I quickly realised calculating averages like that wasn't feasible, so I created five new columns - rating1, rating2, rating3, rating4, rating5. So when 5 users rating something 4 stars, rating4 says 5... does that make sense? Each ratingx column counts the number of times the rating was given.
So anyway: I have this SQL statement:
SELECT id, (ifnull(rating1,0) + ifnull(rating2,0) + ifnull(rating3,0) + ifnull(rating4,0) + ifnull(rating5,0)) /
((rating1 IS NOT NULL) + (rating2 IS NOT NULL) + (rating3 IS NOT NULL) + (rating4 IS NOT NULL) + (rating5 IS NOT NULL)) AS average FROM code
Again messy, but hey. Now what I need to know is how can I incorporate that SQL statement into my script? Ideally you'd think the overall query would be 'SELECT * FROM code ORDER BY (that really long query i just stated) DESC' but I can't quite see that working... how do I do it? Query, store the result in a variable, something like that?
If that makes no sense sorry! But I really appreciate the help :)
Jack
You should go back to the drawing board completely.
<?php
$query = $this->db->query("SELECT * FROM code ORDER BY rating DESC");
foreach($query->result() as $row) {
$this->db->query("SELECT email FROM users WHERE id = ".$row->author;
}
Anytime you see this in your code, stop what you're doing immediately. This is what JOINs are for. You almost never want to loop over the results of a query and issue multiple queries from within that loop.
SELECT code.*, users.email
FROM code
JOIN users ON users.id = code.author
ORDER BY rating DESC
This query will grab all that data in a single resultset, removing the N+1 query problem.
I'm not addressing the rest of your question until you clean up your question some and clarify what you're trying to do.
if you would like to change your tables again, here is my suggestion:
why don't you store two columns: RatingTotal and RatingCount, each user that rates it will increment RatingCount by one, and whatever they vote (5,4,4.2, etc) is added to RatingTotal. You could then just ORDER BY RatingTotal/RatingCount
also, I hope you store which users rated each item, so they don't vote multiple times! and swing the average their way.
First, I'd decide whether your application is write-heavy or read-heavy. If there are a lot more reads than writes, then you want to minimize the amount of work you do on reads (like this script, for example). On the assumption that it's read-heavy, since most webapps are, I'd suggest maintaining the combined average in a separate column and recalculating it whenever a user adds a new rating.
Other options are:
Try ordering by the calculated column name 'average'. SQL Server supports this. . not sure about mysql.
Use a view. You can create a view on your base table that does the average calculation for you and you can query against that.
Also, unrelated to your question, don't do a separate query for each user in your loop. Join the users table to the code table in the original query.
You should include it in the SELECT part:
SELECT *, (if ....) AS average FROM ... ORDER BY average
Edit: assuming that your ifnull statement actually works...
You might also want to look into joins to avoid querying the database again for every user; you can do everything in 1 select statement.
Apart from that I would also say that you only need one average and the number of total votes, that should give you all the information you need.
Some excellent ideas, but I think the best way (as sidereal said that it's more read heavy that write heavy) would be to have columns rating and times_rated, and just do something like this:
new_rating = ((times_rated * rating) + current_rating) / (times_rated + 1)
current_rating being the rating being applied when the person clicks the little stars. This simply weights the current user's rating in an average with the current rating.

Can this query be done without a loop?

So, basically, I have a MySQL table called 'topics' and another one called 'replies', for example. In table 'topics', there's a field called 'relforum' which relates this topic to a forum section. And in the table 'replies', there's a field called 'reltopic', which relates the reply to a topic. Both tables have an id field, auto_increment primary key.
Now, I want to select all replies from a certain forum. Since 'replies' has no 'relforum' field, my way would be:
Select all topics with 'relforum' equal to that certain forum and loop through them
While in the loop, select all replies from the topic that is being 'processed' right now
Merge all fetch_array results in one multidimensional array, then loop through them.
That's something like this:
$query = mysql_query("SELECT * FROM `topics` WHERE `relforum` = '1'");
while($array = mysql_fetch_array($query)) {
$temp = mysql_query("SELECT * FROM `replies` WHERE `reltopic` = {$array['id']}");
$results[] = mysql_fetch_array($temp);
}
Is there a way to merge all that into fewer queries? Because this process would basically run one query per topic in that forum plus one. That would be too much :P
Adding the relforum field to the replies table is a solution (I'm still designing the DB Part so it's not a problem to add it), but I would like to see if there's a solution.
I'm really not good at SQL things, I only know the basic SELECT/INSERT/UPDATE, and I usually generate the last two ones using PHPMyAdmin, so... I guess I need some help.
Thanks for reading!
You need to learn to use joins. The link below is for SQL server but the theory for mySQl is pretty much the same for basic joins. Please do not use comma-based joins as they are 18 years outdated and are a porr pracitce. Learn to use the ANSII standard joins.
http://www.tek-tips.com/faqs.cfm?fid=4785
In accessing a database, you almost never want to use any looping. Databases are designed to perform best when asked to operate on sets of data not individual rows. So you need to stop thinking about looping and start thinking about the set of the data you need.
SELECT
r.*
FROM
replies r
INNER JOIN
topics t
ON
r.reltopic = t.id
WHERE
t.relforum = 1;
You basically need a join of two tables.
SELECT * FROM `replies`, `topics` WHERE `replies`.`reltopic` = `topics`.`id` AND `topics`.`relforum` = '1';
SELECT r.* FROM replies r, topics t
WHERE t.relforum = 1 AND r.reltopic = t.id
get rid of the backquotes. they're nonstandard and clutter the code
Yes, you should use a join here. However you will need to take greater care processing your result set.
Joins are the essential query in a relational database schema. Add them to your arsenal of knowledge :)

Categories