SQL SELECT query echoing twice even with DISTINCT - php

I am creating a simple SQL query in PHP - and for some reason, even when DISTINCT is used, it shows twice like this:
BC
BC
OH
OH
TX
TX
Here is my code:
<?php
$sql = "SELECT DISTINCT `title`,`extra_fields_search` FROM `blahblah_items` WHERE catid=336 ORDER BY `blahblah_items`.`extra_fields_search` ASC ";
$partnerlisting= mysql_query($sql) or die(mysql_error());
while($row = mysql_fetch_assoc($partnerlisting))
foreach($row as $cname => $cvalue){
echo '<li>'.substr($row[extra_fields_search], 0, 2).'</li><br>';
}
;
?>
How can I make it so it prints out only one of each?

SELECT
`title`,
`extra_fields_search`
FROM
`blahblah_items`
WHERE
catid=336
GROUP BY
SUBSTRING(extra_fields_search,1,2) # here. group by first two characters of extra_fields_search
# or just "GROUP BY extra_fields_search", depends what you need
ORDER BY
`blahblah_items`.`extra_fields_search` ASC
SELECT DISTINCT a,b FROM table works in same way as SELECT a,b FROM table GROUP BY a,b
Please follow documentation:
http://dev.mysql.com/doc/refman/5.0/en/distinct-optimization.html
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html

Distinct make sure that you get unique rows. It does not make sure you will get unique column values. In your case if you consider all the fields in the result, you will notice that each row is different from the other by at least one field.
SO you will never get
Col1 Col2
A B
A B
But you can get
Col1 Col2
A B
A C

Try:
SELECT `title`, group_concat(distinct `extra_fields_search`)
FROM `blahblah_items`
WHERE catid=336
Group BY `title`
ORDER BY 2

try this
SELECT `title`,`extra_fields_search`
FROM `blahblah_items` WHERE catid=336
Group BY extra_fields_search
ORDER BY `blahblah_items`.`extra_fields_search` ASC
edit :
try this in your code
while($row = mysql_fetch_assoc($partnerlisting))
$rows[] = $row;
foreach($rows as $row){
echo '<li>'.substr($row[extra_fields_search], 0, 2).'</li><br>';
}
;

Related

PHP Calculate rank from database

I got a little problem, I've got a database, in that database are different names, id, and coins. I want to show people their rank, so your rank has to be 1 if you have the most coins, and 78172 as example when your number 78172 with coins.
I know I can do something like this:
SELECT `naam` , `coins`
FROM `gebruikers`
ORDER BY `coins` DESC
But how can I get the rank you are, in PHP :S ?
You can use a loop and a counter. The first row from MySql is going the first rank,I.e first in the list.
I presume you want something like:
1st - John Doe
2nd - Jane Doe
..
..
right?
See: http://www.if-not-true-then-false.com/2010/php-1st-2nd-3rd-4th-5th-6th-php-add-ordinal-number-suffix
Helped me a while ago.
You could use a new varariable
$i = "1";
pe care o poti folosi in structura ta foreach,while,for,repeat si o incrementezi mereu.
and you use it in structures like foreach,while,for,repeat and increment it
$i++;
this is the simplest way
No code samples above... so here it is in PHP
// Your SQL query above, with limits, in this case it starts from the 11th ranking (0 is the starting index) up to the 20th
$start = 10; // 0-based index
$page_size = 10;
$stmt = $pdo->query("SELECT `naam` , `coins` FROM `gebruikers` ORDER BY `coins` DESC LIMIT {$start}, {$page_size}");
$data = $stmt->fetchAll();
// In your template or whatever you use to output
foreach ($data as $rank => $row) {
// array index is 0-based, so add 1 and where you wanted to started to get rank
echo ($rank + 1 + $start) . ": {$row['naam']}<br />";
}
Note: I'm too lazy to put in a prepared statement, but please look it up and use prepared statements.
If you have a session table, you would pull the records from that, then use those values to get the coin values, and sort descending.
If we assume your Session table is sessions(session_id int not null auto_increment, user_id int not null, session_time,...) and we assume that only users who are logged in would have a session value, then your SQL would look something like this: (Note:I am assuming that you also have a user_id column on your gebruikers table)
SELECT g.*
FROM gebruikers as g, sessions as s WHERE s.user_id = g.user_id
ORDER BY g.coins DESC
You would then use a row iterator to loop through the results and display "1", "2", "3", etc. The short version of which would look like
//Connect to database using whatever method you like, I will assume mysql_connect()
$sql = "SELECT g.* FROM gebruikers as g, sessions as s WHERE s.user_id = g.user_id ORDER BY g.coins DESC";
$result = mysql_query($sql,$con); //Where $con is your mysql_connect() variable;
$i = 0;
while($row = mysql_fetch_assoc($result,$con)){
$row['rank'] = $i;
$i++;
//Whatever else you need to do;
}
EDIT
In messing around with a SQLFiddle found at http://sqlfiddle.com/#!2/8faa9/6
I came accross something that works there; I don't know if it will work when given in php, but I figured I would show it to you either way
SET #rank = 0; SELECT *,(#rank := #rank+1) as rank FROM something order by coins DESC
EDIT 2
This works in a php query from a file.
SELECT #rank:=#rank as rank,
g.*
FROM
(SELECT #rank:=0) as z,
gebruikers as g
ORDER BY coins DESC
If you want to get the rank of one specific user, you can do that in mysql directly by counting the number of users that have more coins that the user you want to rank:
SELECT COUNT(*)
FROM `gebruikers`
WHERE `coins` > (SELECT `coins` FROM `gebruikers` WHERE `naam` = :some_name)
(assuming a search by name)
Now the rank will be the count returned + 1.
Or you do SELECT COUNT(*) + 1 in mysql...

Add 2 row counts together in MySql

I am adapting something and I need to add 2 row counts together in mysql. So far I have
<?
$result = mysql_query("SELECT * FROM Table1 WHERE Field1 ='2' ");
$num_rows = mysql_num_rows($result);
$result2 = mysql_query("SELECT * FROM Table2 WHERE Field2 ='6' ");
$num_rows2 = mysql_num_rows($result2);
$num_rows3 = ($num_rows + $num_rows2)
echo "$num_rows3";
?>
I can echo either $num_rows OR $num_rows2 fine but I need to do the calculation then echo $num_rows3.
I am probably doing something stupid here but I do not know mysql at all so I am trying to learn.
Thanks for the help!
You could also have one single query for both counts:
SELECT count(t1.id), count(t2.id)
FROM (SELECT id FROM Table1 WHERE Field1 ='2') t1,
(SELECT id FROM Table2 WHERE Field2 ='6') t2
Also note that you are missing a ; when summing the counts.
This is just a suggestion even though you got your answer.
If you want to add those into ONE MYSQLI query you could use this:
SELECT sum(cnt) from
(SELECT COUNT(*) cnt FROM T1 WHERE Field1=2 union all
SELECT COUNT(*) cnt FROM T2 WHERE Field2=6) a
I just don't see the point in fetching all data in SELECT * FROM Where all you do is mysql_num_rows($result)
Hope this helps, and maybe improves your code.
Good Luck!
Here is just a demo IN SQLFiddle, so you can see this in action:
SQLFiddle Demo
I was missing the ; after the calculation!!
Using only one query and counting before add, a possible code is
<?
$query = "SELECT c1 + c2 FROM ";
$query .= "(SELECT count(Field1) c1 FROM Table1 WHERE Field1 ='2') t1,";
$query .= "(SELECT count(Field2) c2 FROM Table2 WHERE Field2 ='6') t2";
$result = mysql_query($query);
$value = mysql_num_rows($result);
echo "$value";
?>

How can I convert these two queries in a loop into a single JOINed query?

I am currently trying to get data from my table (mostKills by Weapon in a table with over 300 kills). Initially I did a normal query
$q = $mysql->query("SELECT * FROM `kills`") or die($mysql->error);
but when I tried to
$query2 = $mysql->query("SELECT `killerID`, COUNT(`killerID`) AS tot_kills FROM `kills` WHERE `killText` LIKE '%$gun%' GROUP BY `killerID` ORDER BY `tot_kills` DESC;") or die($mysql->error);
$kData = $query2->fetch_assoc();
$query3 = $mysql->query("SELECT `Username` FROM `players` WHERE `ID` = '" . $kData['killerID'] . "'") or die($mysql->error);
$uData = $query3->fetch_assoc();
$array[$gun]['Kills']++;
$array[$gun]['Gun'] = $gun;
$array[$gun]['BestKiller'] = $uData['Username'];
$array[$gun]['killAmount'] = $kData['tot_kills'];
function sortByKills($a, $b) {
return $b['Kills'] - $a['Kills'];
}
usort($array, 'sortByKills');
foreach($array as $i => $value)
{
// table here
}
I had to do it in a while loop, which caused there to be around 600 queries, and that is obviously not acceptable. Do you have any tips on how I can optimize this, or even turn this into a single query?
I heared JOIN is good for this, but I don't know much about it, and was wondering if you guys could help me
Try this...
I added a inner join and added a username to your select clause. The MIN() is just a way to include the username column in the select and will not have an impact on you result as long as you have just 1 username for every Killerid
SELECT `killerID`
, COUNT(`killerID`) AS tot_kills
, MIN(`Username`) AS username
FROM `kills`
INNER JOIN `players`
ON `players`.`id` = `kills`.`killerid`
WHERE `killText` LIKE '%$gun%'
GROUP BY `killerID`
ORDER BY `tot_kills` DESC
SELECT kills.killerID, count(kills.killerID) as killTotal, players.Username
FROM kills, players
WHERE kills.killText
LIKE '%$gun%'
AND players.ID` = kills.killerID
GROUP BY kills.killerID
ORDER BY kills.tot_kills DESC
Here is a good place to learn some more about joins.
http://www.sitepoint.com/understanding-sql-joins-mysql-database/
The best way is to have your own knowledge so you can be able to tune up your select queries.
Also put more indexes to your DB, and try to search and join by index.

how to solve this mysql query

I have 3 mysql tables
user(u_id(p),name),
team(t_id(p),u_id(f),t_name,t_money,days_money) and
history(t_id(f),day,d_money).
Now I have to display leaderboard using php.
I tried this.
SELECT t_id FROM team;
got result.
then,
in for loop
foreach($tid_all as $tid)
{
$que = $db_con->prepare("SELECT d_money, t_name FROM team, history WHERE t_id= '".$tid['t_id']."' && day='1'");
$que->execute();
while($info = $que->fetch(PDO::FETCH_NUM))
{
echo "<tr>";
echo "<td>".$info[0]."</td>";
echo "<td>".$info[1]."</td>";
echo "</tr>";
}
}
but it didnt work. any solution?
Solution 1:
i tried this and it worked.
`SELECT d_money, t_name FROM team, history WHERE history.t_id=$tid['t_id'] AND team.t_id=history.t_id`
is it correct way or not?
thanks everyone for help.
Question : is it possible to order the result table by d_money? i want it in descending order.
Replace && with AND.Try like this :
"SELECT d_money, t_name FROM team, history WHERE t_id= '".$tid['t_id']."' AND day='1' order by d_money DESC "
There is no && in MySQL Query. Replace that with AND Operator on your query.
Since you want to get the data from the two tables, then JOIN the two tables instead of doing that with a loop:
SELECT
h.d_money,
t.t_name
FROM team AS t
INNER JOIN history AS h ON t.t_id = h.t_id;
Run this single query once and you will get what you want. You can also add a WHERE clause at the end of it the way you did in your query.
try this
SELECT d_money, t_name FROM team, history WHERE team.t_id= '".$tid['t_id']."' AND history.t_id= '".$tid['t_id']."' && day='1'
Can you replace
WHERE t_id= '".$tid."' AND day='1'
instead of
WHERE t_id= '".$tid['t_id']."' && day='1'

Get all rows not matching with another table

I've a tricky question. I have a table with numbers:
37823782
37823782
37823782
38478934
90003922
And another table with prefixes:
378
3847
384
001
I want to find all numbers matching the longest prefix. I succeded with this code:
$result = mysql_query("SELECT numbers FROM table1 GROUP BY numbers") or die ("Query error code 1");
while($row = mysql_fetch_array($result))
{
$numbers =$row["numbers"];
$result2 = mysql_query("SELECT * FROM table2 WHERE '".$numbers."' LIKE CONCAT(prefix, '%') ORDER BY CHAR_LENGTH(prefix) DESC LIMIT 1");
while($row2 = mysql_fetch_array($result2))
{
// That's it
}
}
Now what i want to simply make the opposite thing. I want to find all numbers not matching any prefix. In short in the above example i made i should get "90003922". I thought to use NOT LIKE CONCAT (prefix, '%') but it's not working. Any idea?
You can try this
SELECT * FROM table2 WHERE '".$numbers."' NOT LIKE 'prefix%'
One-query solution will look like this. Try it
SELECT * FROM table1 LEFT JOIN table2 ON table1.numbers LIKE CONCAT(table2.prefix,'%') WHERE table2.prefix IS NULL

Categories