I want to get Name and corresponding Score at the latest time. So I tried:
$queryObj = mysql_query("SELECT `Name`,`Score` from `Table`.`Score` where `Date` = ( SELECT max(`Date`) from `Table`.`Score`) and `Name`<>'' ");
then get value from it by:
while( $obj = mysql_fetch_object( $queryObj ) ) {
$data = array();
$data['Name'] = $obj->Name;
$data['Score'] = $obj->Score;
$searches[] = $data;
}
But when I print :
print_r(array_values($searches));
the first value is missing in the array, so that won't be the right way.
I also tried:
$row = mysql_fetch_assoc($queryObj);
for ($i = 0; $i <3; $i++)
print( $row['Name'][$i]." Score: ".$row['Score'][$i]."<br />\n");
But it won't give me the right results also. How do I get the value from that query? (the query is correct, I tested it). Any body has suggestion ?
Edit: I add my sample data here:
Name Score Date
abc 3 2013-08-29 10:11:47
abc 2 2013-08-29 09:39:23
abc 1 2013-08-28 10:22:28
jane 2 2013-08-29 09:39:23
2013-08-29 10:08:36
jane 1 2013-08-29 10:11:47
tarzan 1 2013-08-29 10:11:47
Note: Yes, there is some blank values.
My expected result would be:
abc score 3
jane score 1
tarzan score 1
Ok, so after you have updated your question and provided what you expect, your query should look like this:
SELECT t1.Name, t1.Score
FROM Table.Score t1
INNER JOIN
(
SELECT max(Date) MaxDate, Name, Score
FROM Table.Score
WHERE Name <> ''
GROUP BY Name
) t2
ON t1.Name = t2.Name AND t1.Date = t2.MaxDate
This will give you pairs of Name and Score for each Name with Score based on his latest Date (1 row per Name).
So replace your original query with mine in this line:
$queryObj = mysql_query(" ... ");
Then:
$rows = array();
while($row = mysql_fetch_assoc($queryObj)) {
$rows[$row['Name']] = $row['Score'];
}
And you can nicely foreach it in the exact way you wanted in your last comment:
foreach($rows as $name => $score) {
echo $name . ' - ' . $score . "\n";
}
Related
I'm very new to PHP/MYSQL and find this quite difficult to explain, so hopefully someone will understand what I'm trying to do. I have a database that collects information on artists and songs. I want to be able to link the artists to the song and display the "credit" with the song information.
I have a database with tables similar to this:
Artist
| artist_id, artist_name
Credits
| credit_id, credit_name
Song
| song_id, song_name
Credit_To_Artist
| credit_id, artist_id, song_id
Example data:
Artist
| 2, Peter Mark
Artist
| 5, Mette Christiansen
Credits
| 1, Producer
Credits
| 2, Writer
Credits
| 3, Vocalist
Song
| 23, The Game
Credit_To_Artist
| 1, 2, 23
Credit_To_Artist
| 2, 2, 23
Credit_To_Artist
| 3, 5, 23
I have created a page "song.php" that displays information on each song using mysql_real_escape_string to get the song ID from the URL:
$id = mysql_real_escape_string($_GET['id']);
if (!$id) {
die('Please provide an id!');
}
$query = "SELECT * FROM `Credit_To_Artist` AS c2a
INNER JOIN `Credits` AS cr ON cr.credit_id = c2a.credit_id
LEFT OUTER JOIN `Artist` AS a ON a.artist_id = c2a.artist_id
LEFT OUTER JOIN `Song` AS s ON s.song_id = c2a.song_id
WHERE c2a.song_id = $id";
$res = mysql_query($query);
$row = mysql_fetch_assoc($res);
The issue I'm having is I want to be able to list all of the artists linked to that song, and all of their credits in brackets next to it. Since there are more than one artist linked to each song, and most of them have more than one credit (producer, writer, vocalist etc), I have no idea how to write a loop function that shows both of these. Below is my attempt to show what I mean, although it obviously doesn't work:
while ($row = mysql_fetch_array($res)) {
$artist = $row[artist_name];
echo "$artist";
while ($row = mysql_fetch_array($res)) {
$credit = $row[credit_name];
echo "$credit";
}
echo "<br />";
}
This is what I'd ideally like to achieve from the example data above:
Song: The Game
Credits: Peter Mark (Producer, Writer)
Mette Christiansen (Vocalist)
You have two options:
GROUP_CONCAT(..)
You can use GROUP_CONCAT(..). This mysql function groups values in a column that are in each group. You would alter the sql to group by artist_id in this case.
SELECT a.artist_name as aname, GROUP_CONCAT(c.credit_name) as credits
FROM Credits_To_Artist as c2a
JOIN Artist as a ON c2a.artist_id = a.artist_id
JOIN Credits as c ON c2a.credit_id = c.credit_id
GROUP BY c2a.credit_id
Your rows would look like:
Array( "aname" => "name",
"credits" => "function 1,function 2" )
The biggest problem with GROUP_CONCAT is that if you have to concat a lot of values together, it might exceed the maximum width of the row. This does not seem to be the case for your problem. You would not need a loop with this approach.
Adding to array
If you keep the query as it is, you have a row for each 'credit'. You can prepare your data by adding it to an Array, then use implode(..) in php to add commas.
$artists = Array();
while( $row = mysql_fetch_array($res) ) {
$artist = $row[artist_name];
$credit = $row[credit_name];
if( !array_key_exists( $artist, $artists ) ) {
$artists[$artist] = Array();
}
$artists[$artist][] = $credit;
}
foreach( $artists as $artist => $creditarr ) {
$credits = implode( ", ", $creditarr );
echo "{$artist} ({$credits})<br>";
}
You'll find that preparing your data in an array will sometimes be much faster than writing a query that does the same thing. I would probably choose the latter solution.
Let's start with the tables, here is what i think you should do
artist | id, name
song | id, title
credit | id, credit
song_artists | id, song_id, artist_id
credit_to_artists | id, song_artists_id, credit_id
Should be the way to handle the kind of relationship you want.
And here is the PHP code, it might not be the most efficient one, but it will do the job
$query = "SELECT * FROM song_artists WHERE song_id = $id_from_link";
$result = mysql_query($query);
while($row = mysql_fetch_array($result))
{
$artistQuery = "SELECT * from artist WHERE id = {$row['artist_id']}";
$artistResult = mysql_query($artistQuery);
while($artistRow = mysql_fetch_array($artistResult))
{
echo "The Artist: " . $artistRow['name'];
}
echo $songArtistId;
$creditToArtistQuery = "SELECT * FROM credit_to_artists WHERE song_artists_id = {$row['id']}";
$creditToArtistResult = mysql_query($creditToArtistQuery);
if(mysql_num_rows($creditToArtistResult)>0)
{
echo " { ";
$isFirstCredit = true;
while($creditToArtistRow = mysql_fetch_array($creditToArtistResult))
{
$creditQuery = "SELECT * FROM credit WHERE id = {$creditToArtistRow['credit_id']}";
$creditResult = mysql_query($creditQuery);
while($creditRow = mysql_fetch_array($creditResult))
{
if($isFirstCredit)
{
echo $creditRow['credit'];
$isFirstCredit = false;
}
else
{
echo ", " .$creditRow['credit'];
}
}
}
echo " } <br />";
}
}
Im trying to find a better way to return 2 tables at once.
My first table is:
[ID] [area]
1 13,12,15
6 18,17,13
and the second table is:
[areaname] [singlearea]
textOf12 12
textOf18 18
textOf15 15
Now, I need to return for each [ID] hits area names, for example:
For the ID: 1, I need the following array: (textOf12,textOf15)
and for the ID 6 I need: (textOf18) only.
This is what i have for now (I don't think its a nice code):
$getall = "SELECT * FROM table1";
$resultfull = mysql_query($getall);
while ($res = mysql_fetch_assoc($resultfull))
{
$uarray = array();
$sqlarea = explode(",", $res['area']);
foreach($sqlarea as $userarea)
{
$areaarray = runquery("SELECT areaname From table2 WHERE singlearea = '".$userarea."'");
$value = mysql_fetch_object($areaarray);
array_push($uarray,$value->areaname);
}
var_dump($uarray);
any suggestions?
Thank you very much!
Comma separated ID list and ID value pretty good matching using like:
select t1.id, t2.areaname
from table1 t1, table2 t2
where concat(',', t1.area, ',') like concat('%,', t2.singlearea, ',%')
However It's recommended to use additional link table!
I got mysql table like this
id | type | number
1 | c | 2
2 | c | 10
3 | c | 20
Also i got PHP array with values:
$array[c] = 5;
$array[d] = 10;
I wanna do something like this
( SELECT * FROM table WHERE number >= $array[ type ] )
so that type could be taken from mysql column somehow and used for finding correct value from array.
Thats kinda tricky, but I'm not sure how better I could ask.
This isn't the most elegant way but something like this?
$where = "WHERE ";
foreach($array as $key => $value)
{
$where .= "(type = $key AND number >= $value) OR";
}
$where = substr($where, 0, strlen($where)-2);
You'd have to attach that to your select statement and then run the query obviously.
Hopefully that allows someone else to catch on and provide a more elegant solution.
Try this:
$type = 'c';
$query = "SELECT * FROM table WHERE number >= " . intval( $array[ $type ] ) . " AND type = '" . $type . "'";
try to do it in two steps:
before use an sql query to put in an array the values of type
then in a while
( SELECT * FROM table WHERE number >= $array[$i] )
where $i is the index of the while loop
Possibly a bit better than using lots of WHERE clauses would be something like this:-
SELECT *
FROM table a
INNER JOIN
(SELECT 'c' AS RowType, 5 AS RowVal
UNION
SELECT 'd', 10) Sub1
ON a.type = Sub1.type AND a.number >= Sub1.RowVal
Set up a subselect which is just getting the constants, and then do a join between that subselect and your existing table.
In php done something like this:-
<?php
$SubQuery = array();
foreach ($array AS $key=>$value)
{
$SubQuery[] = "SELECT '$key' AS RowType, $value AS RowVal";
}
$sql = "SELECT *
FROM table a
INNER JOIN (".implode(" UNION ", $SubQuery).") Sub1
ON a.type = Sub1.type AND a.number >= Sub1.RowVal";
?>
I have this sql statement joining 3 tables:
SELECT * FROM `int_news`
LEFT JOIN tl_member ON int_news.member_id = tl_member.id
LEFT JOIN tl_news ON int_news.news_id = tl_news.id
The 3 Tables are like this:
Table 1 (int_news)
ID, member_id, news_id
Table 2 (tl_member)
id, firstname, lastname
Table 3 (tl_news)
id, headline
So far so good, but it seems i have a big blackhole in my head making me unable to solve how to output the result like this
For each "headline" i want ALL lastnames e.g.
headline 1 Jonny
Walker
Jim
headline 2 Knopf
Jon
Doe
It sounds your looking something like a pivot so if you group your query by headline, it will display each lastname as a column.
I found this good tutorial on pivots for mysql that might help you http://www.artfulsoftware.com/infotree/queries.php#78
headline 1 Jonny Walker Jim
headline 2 Knopf Jon Doe
Here is a loop that would do that *Forgive my php it's been a while.
$curHeadline = "";
while ( $db_field = mysql_fetch_assoc($result) ) {
if($curHeadline != $db_field['headline'])
{
$curHeadline = $db_field['headline'];
print $curHeadline . $db_field['ID']
}
print $db_field['lastName'] . "<BR>";
}
Try this for mysql :
SELECT tlnews.headline, GROUP_CONCAT(tl_member.last_name)
FROM `int_news` LEFT JOIN tl_member ON int_news.member_id = tl_member.id
LEFT JOIN tl_news ON int_news.news_id = tl_news.id
GROUP BY 1;
Expected Output:
headline1 Johnny,Walker,Jim
headline2 Knopf,Jon,Doe
...
Would something like this vaguely reflect your situation?
<?php
$sql = "
SELECT
`int_news`.`ID` AS `int_news_ID`,
`int_news`.`member_id`,
`int_news`.`news_id`,
`t1_member`.`id` AS `t1_member_id`,
`t1_member`.`firstname`,
`t1_member`.`lastname`, /* desired */
`t1_news`.`id` AS `t1_news_id`,
`t1_news`.`headline` /* desired */
FROM
`int_news`
LEFT JOIN `tl_member` ON `int_news`.`member_id` = `tl_member`.`id`
LEFT JOIN `tl_news` ON `int_news`.`news_id` = `tl_news`.`id`
";
$res = mysql_query($query);
$arrHeadings = array();
while($row = mysql_fetch_assoc($res)) {
// We want to output the results in groups of headings
$arrHeadings[$row['heading']][] = $row;
}
// Don't forget to cleanse for html output (unlike below)
// Loop through the headers
foreach($arrHeadings as $heading=>$arrRow) {
echo '<dl>';
echo '<dt>'.$heading.'</dt>';
echo '<dd>';
// Loop through rows with the same header
foreach($arrRow as $index=>$dbRow) {
echo $dbRow['lastname'].'<br />';
}
echo '</dd>';
echo '</dl>';
}
?>
I have two tables like so:
table {node}
`nid`, `uid`, `type`
1 1 basketball
2 1 basketball
3 1 football
4 2 football
5 2 basketball
table {strato_ticket}
`tid`, `author_uid`, `purpose`, `active`
1 1 'Ticket to a basketball game' TRUE
2 1 'Ticket to a football game' TRUE
3 2 'Ticket to a football game' FALSE
I'd like to generate a report that counts the number of each kind of node, and then counts the number of active tickets that each user has associated with that kind of node.
My solution uses a combination of SQL and PHP: I have a PHP loop for each kind of node that I'm interested in, which simplifies the SQL query, and translates from 'type' to 'purpose', eg
$node_types = array('basketball', 'football');
foreach($node_types as $node){
switch($type){
case 'basketball':
$purpose = array('Ticket to a basketball node');
break;
case 'football':
$purpose = array('Ticket to a football game');
break;
}
$where = " WHERE ({strato_ticket}.`purpose` = '"
.implode("' OR {strato_ticket}.`purpose` = '",$purpose)."')";
Finally I have the trouble spot, the SQL query. When I was just counting nodes owned by each user, it worked fine:
$query = "
SELECT uid, count( * ) AS nodes_owned
FROM {node} WHERE `type` = '$type'
GROUP BY uid ORDER BY nodes_owned DESC
";
$query = db_query($query);
output:
Now displaying info for basketball.
uid nodes_owned
1 2
2 1
Now displaying info for football.
uid nodes_owned
1 1
2 1
But now that I need to query against another table, strato_ticket, things get complicated, and my query is returning FALSE without throwing an error (I think).
$query = "
SELECT count(*) as tickets
FROM {strato_ticket} INNER JOIN (
SELECT node.uid, count( * ) AS nodes_owned
FROM {node} WHERE `type` = '$type'
GROUP BY uid
) AS {nodecount}
ON {strato_ticket}.`author_uid` = {nodecount}.`uid`
$where
GROUP BY nodecount.uid ORDER BY nodecount.nodes_owned DESC
";
$query = db_query($query);
I'm not very good with SQL and I'm not quite sure how it's broken. Could use a little help?
Ideally would like to see
uid nodes_owned tickets
//basketball
1 2 1
2 1 0
//football
1 1 1
2 1 0
Aside from the placeholders, which I can get to later, I think this solves it.
$form = array();
$node_types = array('basketball','football');
// if($user->uid == 1){
$form[$type][] = array('#value'=>"Showing how many of each node type each user owns.".'<br/>');
foreach($node_types as $type){
// Count the number of nodes each user owns of $type.
$form[$type][] = array('#value'=>"Now displaying info for $type".'s. <br/>');
switch($type){
case 'basketball':
$purpose = array('ticket to a basketball game', 'basketball');
break;
case 'football':
$purpose = array('ticket to a football game');
break;
}
$purpose = implode("', '", $purpose);
//#todo : Make a temporary table to query against so I'm not hitting node table multiple times.
$ticketquery = "
SELECT author_uid, purpose, COUNT( * ) AS invitees_accepted
FROM {strato_ticket}
WHERE purpose IN ('$purpose')
GROUP BY author_uid, `purpose`
";
$nodequery = "
SELECT node.uid, count( * ) AS nodes_owned, type
FROM {node}
WHERE `type` IN ('$type')
GROUP BY uid, type";
$query = "
SELECT * FROM
($nodequery) AS nt
JOIN
($ticketquery) AS tt
ON nt.uid = tt.author_uid
GROUP BY nt.uid ORDER BY nt.nodes_owned DESC
";
drupal_set_message('Query is <br/>'.$query);
//return;
$query = db_query($query);
$first = true;
while ($rec = db_fetch_object($query)){
if($first){
$form[$type][] = array('#value'=>"And the winner is: ".print_r($rec, true).'<br/>');
$first = false;
}
else {
$form[$type][] = array('#value'=>print_r($rec, true).'<br/>');
}
}
// }
}