A logical problem with two tables - php

Hey guys, I created a list for fixtures.
$result = mysql_query("SELECT date FROM ".TBL_FIXTURES." WHERE compname = '$comp_name' GROUP BY date");
$i = 1;
$d = "Start";
while ($row = mysql_fetch_assoc($result))
{
$odate = $row['date'];
$date=date("F j Y", $row['date']);
echo "<p>Fixture $i - $d to $date</p>";
}
As you can see from the query, the date is displayed from the fixtures table.
The way my system works is that when a fixture is "played", it is removed from this table. Therefore when the entire round of fixtures are complete, there wont be any dates for that round in this table. They will be in another table.
Is there anyway I can run an other query for dates at the same time, and display only dates from the fixtures table if there isnt a date in the results table?
"SELECT * FROM ".TBL_CONF_RESULTS."
WHERE compid = '$_GET[id]' && type2 = '2' ORDER BY date"
That would be the second query!
EDIT FROM HERE ONWARDS...
Is there anyway I can select the date from two tables and then only use one if there are matches. Then use the rows of dates (GROUPED BY) to populate my query? Is that possible?

It sounds like you want to UNION the two result sets, akin to the following:
SELECT f.date FROM tbl_fixtures f
WHERE f.compname = '$comp_name'
UNION SELECT r.date FROM tbl_conf_results r
WHERE r.compid = '$_GET[id]' AND r.type2 = '2'
GROUP BY date
This should select f.date and add rows from r.date that aren't already in the result set (at least this is the behaviour with T-SQL). Apparently it may not scale well, but there are many blogs on that (search: UNION T-SQL).

From the notes on this page:
//performs the query
$result = mysql_query(...);
$num_rows = mysql_num_rows($result);
//if query result is empty, returns NULL, otherwise,
//returns an array containing the selected fields and their values
if($num_rows == NULL)
{
// Do the other query
}
else
{
// Do your stuff as now
}

WHERE compid = '$_GET[id]' presents an oportunity for SQL Injection.
Are TBL_FIXTURES and TBL_CONF_RESULTS supposed to read $TBL_FIXTURES and $TBL_CONF_RESULTS?

ChrisF has the solution!
One other thing you might think about is whether it is necessary to do a delete and move to another table. A common way to solve this type of challenge is to include a status field for each record, then rather than just querying for "all" you query for all where status = "x". For example, 1 might be "staging", 2 might be "in use", 3 might be "used" or "archived" In your example, rather than deleting the field and "moving" the record to another table (which would also have to happen in the foreach loop, one would assume) you could simply update the status field to the next status.
So, you'd eliminate the need for an additional table, remove one additional database hit per record, and theoretically improve the performance of your application.

Seems like what you want is a UNION query.
$q1 = "SELECT DISTINCT date FROM ".TBL_FIXTURES." WHERE compname = '$comp_name'";
$q2 = "SELECT DISTINCT date FROM ".TBL_CONF_RESULTS.
"WHERE compid = '$_GET[id]' && type2 = '2'";
$q = "($q1) UNION DISTINCT ($q2) ORDER BY date";

Related

PHP Output data from 3 different tables

I'm trying to display a HTML table with information from 3 different tables in my mysql DB. However I am unsure on how to display the information from the third table.
Currently what I am using is:
$SQL = "SELECT members.*, exp.*, lvl.*
FROM members
INNER JOIN exp ON members.id = exp.member_id
INNER JOIN lvl ON members.id = lvl.member_id
ORDER BY lvl.level DESC,
lvl.total DESC, xp.total DESC";
$result = mysql_query($SQL) or die(mysql_error());
$count = 1;
while ($row = mysql_fetch_assoc($result)) {
$level = $row['level'];
$exp = $row['exp.overall'];
}
the $level is from the second table which grabs correctly, and the $exp is what I want to grab from the third table which is "exp" but it doesn't return anything
How can I change this because at the moment it just seems to be focusing on the data from the "lvl" table when using $row[]
Edit: Both the lvl and exp tables have a row in called 'overall' which is why using $row['overall'] doesn't return what I want as it returns the data from lvl table rather than exp.
First off I believe you have a typo in your last order column: should be exp.total DESC.
Secondly, unless you specify the columns to be named with dot notation explicitly they will retain their column names so try changing the last line to:
$exp = $row['overall'];.
Also consider using mysqli or PDO.

Find out how often a value is between 2 dates in mysql

Hi with the follow code I request what dates are all in my database without duplicates.
Then I save it to an array. In the array I also need an other value.
The value I need is how much users are in one day in the database without duplicates.
For Example the array must later lookslike 23.07.2013 - 10, 24.07.2013 - 50 (users).
I search for several hours but I don't find a good mysql query.
$query = "SELECT id, user, timestamp FROM stat WHERE timestamp BETWEEN '$datum1' AND '$datum2' GROUP BY timestamp";
$result = mysql_query($query,$db);
while($row = mysql_fetch_assoc($result))
{
mysql_num_rows($result);
$dataset1[] = array(strtotime($row['timestamp']),$number_of_users_on_this_day);
}
Try:
$query = "SELECT id, user, COUNT(*) as count FROM stat WHERE timestamp BETWEEN '$datum1' AND '$datum2' GROUP BY timestamp";
This will return the number of entries in the value 'count'
if you want distinct data, in place of * use
COUNT(DISTINCT id)
with whatever field you want to be unique in place of 'id'

MySQL query from a query result in php

How should I go if I wanted to query a query result in php?
Supose I have this..
$result = mysql_query("SELECT * FROM tbl_x WHERE tbl_x.attribute = y");
And now I need to query that $result to filter the results I got from its query. Note that I don't want to do this...
$result2 = mysql_query("SELECT * FROM ( SELECT * FROM tbl_x WHERE tbl_x.attribute = y ) AS tbl_x1 WHERE tbl_x1... etc");
The reason I want to avoid that is I'm getting a "Duplicate column" error when executing a query like that.
I'm looking for something like...
$result = mysql_query("SELECT * FROM tbl_x");
$result2 = mysql_query_result($result);
You can apply more than one term in your search conditions, separated by AND:
$result = mysql_query("SELECT * FROM tbl_x
WHERE tbl_x.attribute = y
AND tbl_x.attribute2 = z");
Re your comments above. It sounds like you are using the Entity-Attribute-Value design.
In order to match multiple attributes, you have to do some tricks. Normally, a WHERE clause can only apply to one row at a time. But since each of your attributes are stored on separate rows, you need to do either one of two solutions:
Join multiple rows into one row, so you can use WHERE on all attributes in one condition.
SELECT config_id
FROM attributes AS s
JOIN attributes AS c USING (config_id)
JOIN attributes AS l USING (config_id)
WHERE (s.attr, s.value) = ('size', 'M')
AND (c.attr, c.value) = ('colour, 'green')
AND (l.attr, l.value) = ('cloth', 'cotton);
Search for any of the several attributes, and then if the number of rows that match is equal to the number of attributes you were searching for, you've found them all.
SELECT config_id
FROM attributes
WHERE (attr, value) = ('size', 'M')
OR (attr, value) = ('colour', 'green')
OR (attr, value) = ('cloth', 'cotton')
GROUP BY config_id
HAVING COUNT(DISTINCT attr) = 3;
You can still have your query of query without getting "duplicate column" error. Just alias and name the columns
$result2 = mysql_query("SELECT tbl_x1.col1, tbl_x1.col2,...etc FROM
(SELECT * FROM tbl_x WHERE tbl_x.attribute = y) AS tbl_x1
WHERE tbl_x1... etc");

What is the query statement to write in order to solve the followin database problem?

I have the following 3 tables in the database.
Programs_Table
Program_ID (Primary Key)
Start_Date
End_Date
IsCompleted
IsGoalsMet
Program_type_ID
Programs_Type_Table(different types of programs, supports a dropdown list in the form)
Program_type_ID (Primary Key)
Program_name
Program_description
Client_Program_Table
Client_ID (primary key)
Program_ID (primary key)
What is the best way to find out how many clients are in a specific program (program type)?
Would the following SQL statement be the best way, or even plausible?
SELECT Client_ID FROM Client_Program_Table
INNER JOIN Programs_Table
ON Client_Program_Table.Program_ID = Programs_Table.Program_ID
WHERE Programs_Table.Program_type_ID = "x"
where "x" is the Program_type_ID of the specific program we're interested in.
OR is the following a better way?
$result = mysql_query("SELECT Program_ID FROM Programs_Table
WHERE Program_type_ID = 'x'");
$row = mysql_fetch_assoc($result);
$ProgramID = $row['Program_ID'];
$result = mysql_query("SELECT * FROM Client_Program_Table
WHERE Program_ID = '$ProgramID'");
mysql_num_rows($result) // returns how many rows of clients we pulled.
Thank you in advance, please excuse my inexperience and any mistakes that I've made.
Here is how you can do it:
<?php
// always initialize a variable
$number_of_clients = 0;
// escape the string which will go in an SQL query
// to protect yourself from SQL injection
$program_type_id = mysql_real_escape_string('x');
// build a query, which will count how many clients
// belong to that program and put the value on the temporary colum "num_clients"
$query = "SELECT COUNT(*) `num_clients` FROM `Client_Program_Table` `cpt`
INNER JOIN `Programs_Table` `pt`
ON `cpt`.`Program_ID` = `pt`.`Program_ID`
AND `pt`.`Program_type_ID` = '$program_type_id'";
// execute the query
$result = mysql_query($query);
// check if the query executed correctly
// and returned at least a record
if(is_resource($result) && mysql_num_rows($result) > 0){
// turn the query result into an associative array
$row = mysql_fetch_assoc($result);
// get the value of the "num_clients" temporary created column
// and typecast it to an intiger so you can always be safe to use it later on
$number_of_clients = (int) $row['num_clients'];
} else{
// query did not return a record, so we have no clients on that program
$number_of_clients = 0;
}
?>
If you want to know how many clients are involved in a program, you'd rather want to use COUNT( * ). MySQL (with MyISAM) and SQL Server have a fast way to retrieve the total number of lines. Using a SELECT(*), then mysql_num_rows leads to unnecessary memory ressources and computing time. To me, this is the fastest, though not the "cleanest" way to write the query you want:
SELECT
COUNT(*)
FROM
Client_Program_Table
WHERE
Program_ID IN
(
SELECT
Program_ID
FROM
Programs_Table
WHERE
Program_type_ID = 'azerty'
)
Why is that?
Using JOIN make queries more readable, but subqueries often prove to be computed faster.
This returns a count of the clients in a specific program type (x):
SELECT COUNT(cpt.Client_ID), cpt.Program_ID
FROM Client_Program_Table cpt
INNER JOIN Programs_Table pt ON cpt.Program_ID=pt.Program_ID
WHERE pt.Program_type_ID = "x"
GROUP BY cpt.Program_ID

Looping out mysql data

I have a mysql database of entries with dates. So what I want is to show all the dates in my database and then under each date, I want to show all the entries in the database entered on the specefic date. I am thinking of two loops but I don't know how to write the condition to display all the dates in my database before I loop out the entries under that date.
Edit: i used NOW() to store the date. Using the loop by longneck, how can ignore the time when checking if date is sameas previous? Should I explode? What's the best way?
you should use one query, sort it by date, and detect the change in the date as a signal to display the next date:
<?php
$sql = 'select start_date, name from events order by start_date';
$res = mysql_query($sql) or die(mysql_error());
$prev_date = null;
while ($row = mysql_fetch_assoc($res)) {
if ($row['start_date'] != $prev_date) {
echo "<h1>{$row['start_date']}</h1>"\n;
$prev_date = $row['start_Date'];
}
echo "<p>{$row['name']}</p>";
}
?>
I'm assuming that you want a list of the dates so that you can then do separate queries for each date's entries. Usually you would use a query like:
SELECT DISTINCT date_field FROM table_name ORDER BY date_field DESC
(this will do it newest-first, remove DESC to make it oldest-first)
Now, you probably don't want to do it this way, because it will require a lot of queries (one for each day's entries). It is more efficient to just order the entries by the date, and then use logic in your php to print out the headers. So you would use code like:
$result = $db->query("SELECT * FROM table_name ORDER BY date_field DESC");
$current_date = "";
while ($row = $result->fetch_array()) {
if ($current_date != $row["date_field"]) {
echo "<h3>{$row['date_field']}</h3>";
$current_date = $row["date_field"];
}
// Print your entry from $row here.
}
you would probably want to get that in your SQL statement: (assuming it is datetime type)
SELECT * FROM table
WHERE date BETWEEN '2009-9-8 00:00:00' AND '2008-9-8
23:59:59'
Then just do your normal loop through your results
Also have a look at the GROUP BY clause of the SELECT statement.

Categories