I'm new at programming. This week I have learned the basics of HTML, CSS, PHP and MySQL and I am making a simple turn-based strategy game to practice coding (and have fun while doing it!).
Now, I usually look on DuckDuckGo and YouTube when I am stuck but this time I can't seem to find an answer to my question. Here it is, hope you can help:
I am making the file that will be a cronjob to update the resources my players have. In table 1 (named stockpile) I have columns called village_id, wood, stone and iron. In table 2 (named buildings) I have columns called village_id, woodcutters, quarry and mine. Now here is an example of what I'd like the code to do:
Take 'wood' of village1 and update it like this; wood = wood + (x * woodcutter of village1).
I really hope someone can help me! My project is going fine except for this part I can't seem to wrap my head around...
use a subquery (replace [x] with some value):
UPDATE stockpile s
SET wood = wood + [x] *
(SELECT woodcutters
FROM buildings b
WHERE b.village_id = s.village_id);
You need to SELECT the columns from the table and get the data for the player from those columns, multiply, and update the table. I'm assuming your village_id is a unique index.
$sql = SELECT COUNT(*) FROM table1;
$result = $conn->query($sql);
$sql1 = "SELECT wood FROM table1";
$result1 = $conn->query($sql);
$arr1 = $result1->fetch_assoc();
$sql2 = "SELECT woodcutter FROM table2";
$result2 = $conn->query($sql2);
$arr2 = $result2->fetch_assoc();
for ($i=1;$i<=$result;$i++) {
$newwood = $arr1[$i] + (x * $arr2[$i]);
$sql3 = "UPDATE table1 SET wood=" . $newwood . " WHERE id=" . $i;
$conn->query($sql3);
}
To make it a cron, you need to configure a job with Apache or your other server.
Related
I was wondering if it's possible to combine these two queries as they do not work separately (one of the two only works). They are
$addquery = "UPDATE winners SET mem_name='$addname' WHERE mem_name='$deletename'";
$addresult= mysqli_query($connect, $addquery);
$query = "UPDATE winners INNER JOIN members SET winners.mem_id = members.mem_id
WHERE winners.mem_name = members.mem_name";
$result = mysqli_query($connect, $query);
Can this be done in just one query? Thank you!!!
I am not saying you should do it, but judging from the flow of the code you provided, this is how you could do it.
UPDATE winners w
SET w.mem_name = '$addname'
, w.mem_id = IFNULL(SELECT m.mem_id
FROM members AS m
WHERE m.mem_name = '$addname'
ORDER BY m.mem_id DESC
LIMIT 1
, w.mem_id
)
WHERE w.mem_name = '$deletename'
;
Note, the ORDER BY is technically optional; your question does not state whether mem_name is guaranteed unique in members. If it is unique, the order by should not be needed; if it is not, it at least adds some consistency to the expected value retrieved.
If you have control over the database design, I would suggest removing mem_name from winners altogether. It is/would be redundant data if you were managing the relation primarily by mem_id to begin with.
I'm trying to get my head around how I would do a particular MYSQL query but can't figure it out.
I have a table called developers and a table called plots. All of the plots have a developer id which links back to a developer name in the developers table.
I'm trying to output the developer name and then all the plots numbers under that developer. Once it's done that, I want it to do the same again with any more developers that may exist.
I've tried using joins however it will simply print:
developer name, plot number,
developer name, plot number,
developer name, plot number,
I only need the developer name to display once. However I need to print all the plot numbers.
I thought about having some kind of IF statement in the while loop where if the developer name is the same as it was previously in the last loop then it wont print. However I can't seem to figure out how that would work.
Thank you all for your help.
you can do in two steps
1. to get developer name and id.
2. get all plots of that id
$sql1 = "SELECT developer_id, developer_name FROM developers ";
$res = mysqli_query($con, $sql1);
while($row = mysqli_fetch_array($res))
{
$developer_id = $row['developer_id'];
$developer_name = $row['developer_name'];
echo $developer_name;
$sql2 = "SELECT * FROM plots WHERE developer_id='$developer_id' ";
$res2 = mysqli_query($con, $sql2);
while($row2 = mysqli_fetch_array($res2))
{
echo $row2['plot_id'];
}
}
This won't give you an output as exactly u need. But maybe this would do the job.
select developer_name, group_concat(plot_number SEPARATOR ',') from developer inner join plot on plot.developer_id = developer.developer_id group by developer_name
You can then explode out(PHP Explode with comma as the delimiter) the plot_number column from the result set to show all the plot numbers corresponding to a developer.
Use a Left Join..
Select * From developers Left Join plots on developers.developerid=plots.developerid
So it'll select everything from table developers and for each developer, it should select the plots.
Use an if condition to check if the last result of the developer id is equal to the current. If it is no, print the id.
Edit:
Here's how the PHP program should run..
$strSQL = "Select * From developers Left Join plots on developers.developerid=plots.developerid";
$Result = mysql_query($strSQL);
$DevID = "";
while ($Fields = mysql_fetch_array($Result))
{
if ($Fields["developerid"] != $DevID)
{
echo $Fields["developerid"];
$DevID = $Fields["developerid"];
}
echo $Fields["plot_column"];
}
Problem solved
The answer was
$query = "SELECT manager FROM tablename WHERE manager='$manager'";
Subtle difference, but removing the dots before and after $manager was the answer.
Credit to PHPFreaks.com
I had this;
<?php include 'dbdetails.php';
$id = mysql_real_escape_string($_GET['id']);
$query = 'SELECT `column` FROM `tablename` WHERE `id` = '.$id.' ';
$result = mysql_query($query);
$row = mysql_fetch_array($result);
echo $row['column'];
?>
(taken from here)
This works fine if I am solely working with an ID, however I have repeated values in the column I need to work with so ID will not work for what I am trying to achieve.
Essentially I am trying to create pages on the fly using the Manager column as the query as opposed to the ID.
What would be the correct way to achieve this? I presume DISTINCT comes into play?
I am aiming for;
Micky Adams
as my structure, where it fetches all instances of Micky Adams or whichever manager name is set up as the anchor.
If you changed it to:
$manager = $_GET['manager'];
$query = 'SELECT `column` FROM `tablename` WHERE `manager` = '.$manager.' ';
Wouldn't that achieve what you want? If you had more than one instance of the manager DISTINCT only partly helps depending how your data is actually stored.
Part of my page I have lots of small little queries, probably about 6 altogether, grabbing data from different tables. As an example:
$sql_result = mysql_query("SELECT * FROM votes WHERE voted_on='$p_id' AND vote=1", $db);
$votes_up = mysql_num_rows($sql_result);
$sql_result = mysql_query("SELECT * FROM votes WHERE voted_on='$p_id' AND vote=0", $db);
$votes_down = mysql_num_rows($sql_result);
$sql_result = mysql_query("SELECT * FROM kids WHERE (mother_id='$p_id' OR father_id='$p_id')", $db);
$kids = mysql_num_rows($sql_result);
Would it be better if these were all grabbed in one query to save trips to the database? One query is better than 6 isn't it?
Would it be some kind of JOIN or UNION?
Its not about number of queries but amount of useful datas you transfer. If you are running database on localhost, is better to let sql engine to solve queries instead computing results in additional programs. The same if you are thinking about who should be more bussy. Apache or mysql :)
Of course you can use some conditions:
SELECT catName,
SUM(IF(titles.langID=1, 1, 0)) AS english,
SUM(IF(titles.langID=2, 1, 0)) AS deutsch,
SUM(IF(titles.langID=3, 1, 0)) AS svensk,
SUM(IF(titles.langID=4, 1, 0)) AS norsk,
COUNT(*)
FROM titles, categories, languages
WHERE titles.catID = categories.catID
AND titles.langID = languages.
example used from MYSQL Bible :)
If you really want to lower the number of queries, you can put the first two together like this:
$sql_result = mysql_query("SELECT * FROM votes WHERE voted_on='$p_id'", $db);
while ($row = mysql_fetch_array($sql_result))
{
extract($row);
if ($vote=='0') ++$votes_up; else ++$votes_down;
}
The idea of joining tables is that these tables are expected to have something in between (a relation, for example).
Same is for the UNION SELECTS, which are prefered to be avoided.
If you want your solution to be clean and scalable in future, I suggest you to use mysqli, instead of mysql module of PHP.
Refer to: mysqli::multi_query. There is OOP variant, where you create mysqli object and call the function as method.
Then, your query should look like:
// I use ; as the default separator of queries, but it might be different in your case.
// The above could be set with sql statement: DELIMITER ;
$query = "
SELECT * FROM votes WHERE voted_on='$p_id' AND vote=1;
SELECT * FROM votes WHERE voted_on='$p_id' AND vote=0;
SELECT * FROM kids WHERE (mother_id='$p_id' OR father_id='$p_id');
";
$results = mysqli_multi_query($db, $query); // Returns an array of results
Fewer queries are (generally, not always) better, but it's also about keeping your code clear enough that others can understand the query. For example, in the code you provided, keep the first two together, and leave the last one separate.
$sql_result = mysql_query("SELECT vote, COUNT(*) AS vote_count
FROM votes
WHERE voted_on='$p_id'
GROUP BY vote", $db);
The above will return to you two rows, each containing the vote value (0 or 1) and the vote count for the value.
I'm doing this project for university, which is basically a movie database and for a couple of queries I need to know how many rows were selected. For now, there's 2 situations where I need this:
Display a single movie information. I want the count of selected rows to know if the database contains the selected movie by the user. Or is there a better solution for this?
That selected movie has genres, I need to know how many so that I can construct a string with the genres separated by | without adding one to the end of the string.
With MySQL this is easy, I just query the database and use mysql_num_rows() but oci_num_rows() doesn't work quite the same for the SELECT statement.
The only solution I found with OCI/PHP is this:
if(is_numeric($mid) && $mid > 0) {
$stid = oci_parse($db,
'SELECT COUNT(*) AS NUM_ROWS
FROM movies
WHERE mid = '.$mid
);
oci_define_by_name($stid, 'NUM_ROWS', $num_rows);
oci_execute($stid);
oci_fetch($stid);
if($num_rows > 0) {
$stid = oci_parse($db,
'SELECT title, year, synopsis, poster_url
FROM movies
WHERE mid = '.$mid
);
oci_execute($stid);
$info = oci_fetch_assoc($stid);
$stid = oci_parse($db,
'SELECT COUNT(*) AS NUM_ROWS
FROM genres g, movies_genres mg
WHERE mg.mid = '.$mid.' AND g.gid = mg.gid'
);
oci_define_by_name($stid, 'NUM_ROWS', $num_rows);
oci_execute($stid);
oci_fetch($stid);
$stid = oci_parse($db,
'SELECT g.name AS genre
FROM genres g, movies_genres mg
WHERE mg.mid = '.$mid.' AND g.gid = mg.gid');
oci_execute($stid);
$genres_list = null;
while($row = oci_fetch_assoc($stid)) {
$genres_list .= $row['GENRE'];
if($num_rows > 1) {
$genres_list .= ' | ';
$num_rows--;
}
}
$Template->assignReferences(array(
'Index:LinkURI' => $link_uri,
'Movie:Title' => $info['TITLE'],
'Movie:Year' => $info['YEAR'],
'Movie:GenresList' => $genres_list,
'Movie:Synopsis' => $info['SYNOPSIS'],
'Movie:PosterURL' => $info['POSTER_URL'] // FIX: Handle empty poster link
));
$Template->renderTemplate('movieinfo');
} else {
// TODO: How to handle this error?
}
} else {
// TODO: How to handle this error?
}
But I don't like it. I always need to make 2 queries to count the rows and then select the actual data and there's too many lines of code just to count the rows.
This code doesn't show it (haven't done it yet cause I'm looking for a better solution) but I'll also need to do the same for the movie directors/writers.
Is there any better and simpler solution to accomplish this or this is the only way?
I could add separators in the fetch loop until it finishes and then use PHP functions to trim the last separator from the string, but for this project I'm forced to use SEQUENCES, VIEWS, FUNCTIONS, PROCEDURES and TRIGGERS. Do any of these help solving my problem?
I know what SEQUENCES are, I'm using them already but I don't see how can they help.
For VIEWS, they probably wouldn't simplify the code that much (it's basically a stored query right?). For FUNCTIONS, PROCEDURES and TRIGGERS, as far as I understand them, I can't see how can they be of any help either.
Solutions?
Why do the initial count at all? Just issue your select for the movie title. If it's not found, do your error processing. If it is, continue on! If you really need the count, use an analytic to add the count to your query:
'SELECT title, year, synopsis, poster_url
, COUNT(*) OVER (PARTITION BY mid) mcount
FROM movies
WHERE mid = '.$mid
The same goes for your genre selection.
EDIT:
Oracle documentation on Analytic Functions link. I found that analytics are a bit difficult to get from the Oracle docs. Analytic functions by Example by Shouvik Basu provides some simple guidance as to how to use them and helped me quite a bit.
You can try this
$conn = oci_pconnect('user', 'password', 'connectionstring');
$resource = oci_parse($conn, $sql);
oci_execute($resource, OCI_DEFAULT);
$results=array();
$numrows = oci_fetch_all($resource, $results, null, null, OCI_FETCHSTATEMENT_BY_ROW);
Cheers
you can use the ocirowcount it should behave just like mysql_num_rows when making a select
oci_num_rows() Will give you the total row count if executed AFTER oci_fetch_array()