real rank in mysql and php - php

I do a simple SQL-Query:
SELECT `name`, `likes`
FROM `social`
WHERE `month` = '2015-01'
ORDER BY `likes` DESC
then I add a "Rank" wich is an intenger with ++
$data = array();
$rank = 0;
while ($table_row = mysqli_fetch_assoc($table)) {
$rank++;
$data[$table_row['name']] = $table_row;
$data[$table_row['name']]['rank'] = $rank;
}
The result is left and what I want on the right side
+------+------+-------+ +------+------+-------+
| rank | name | likes | | rank | name | likes |
+------+------+-------+ +------+------+-------+
| 1 | foo | 123 | | 1 | foo | 123 |
| 2 | mfoo | 33 | | 2 | mfoo | 33 |
| 3 | xfoo | 33 | | 2 | xfoo | 33 |
| 4 | yfoo | 30 | | 4 | yfoo | 30 |
| 5 | zfoo | 29 | | 5 | zfoo | 29 |
+------+------+-------+ +------+------+-------+
how do I get the right side table? is there a way to solve it in the query?
EDIT:
There I am standing now:
select IF(#likes=s.likes, #rownum, #rownum:=#rownum+1) rank2,
s.domain_name, s.likes,
(#likes:=s.likes) dummy
from social s,
(SELECT #rownum:=0) x,
(SELECT #likes:=0) y
WHERE `month` = '2015-01'
order by likes desc
but the rank is not 100% correct because I want to skip a rank instead of counting through

I see what's happening here.
I dont know about best practices but I'd probably do something like this myself:
$data = array();
$rank = 0;
$lastlike = 1;
$currentlike = 0;
$i = 0;
while ($table_row = mysqli_fetch_assoc($table)) {
$name = $table_row['name'];
$currentlike = $table_row['likes'];
if ($currentlike != $lastlike) $rank++;
$data[$i] = array('rank'=>$rank,'name'=>$name,'likes'=>$currentlike);
$lastlike = $currentlike;
$i++;
}
I've not checked it but you're welcome to try it out and see.

You can do this with SQL or with PHP (you can test to know which one is the faster).
Note : this 2 solutions will give you a rank which start at 0.
SQL :
SELECT
`name`,
`likes`,
(SELECT COUNT(*) FROM `social` AS S2 WHERE S1.likes > S2.likes) AS `rank_2`
FROM `social` AS S1
WHERE `month` = '2015-01'
ORDER BY `likes` DESC
PHP :
$data = array();
$rank = 0;
$likes_pre = -1;
while ($table_row = mysqli_fetch_assoc($table)) {
$likes_cur = $table_row['likes'];
if ($likes_pre > $likes_cur) {
$rank++;
}
$data[$table_row['name']] = $table_row;
$data[$table_row['name']]['rank'] = $rank;
$likes_pre = $likes_cur;
}
Not tested, but it should work.

Try this... rank should be the same for all rows with the same number of likes
$data = array();
$rank = 0;
$last_likes =0;
while ($table_row = mysqli_fetch_assoc($table)) {
if ($last_likes != $row['likes']) {
$rank++;
}
$data[$table_row['name']] = $table_row;
$data[$table_row['name']]['rank'] = $rank;
}

Related

Delete and fill the information

Hello I have this table and I want to be able to delete the data on P(number) and tituloP(number).
I have done the query to delete if the user choose the last P(number) its the easier.
Now I have to do a cicle that if user delete a middle data it auto fill 1 field.
There is the example:
IIDD | ID | Num_Slides | P1 | P2 | P3 | P4 | P5 | tituloP1 | tituloP2 | tituloP3 | tituloP4 | tituloP5
1 | 4 | 5 | 1 | 2 | 4 | 5 | 2 |Sometext |Sometext2 |Sometext3 |Sometext4 |Sometext5 |
If user choose to delete P5 its easier I just need to fill the P5 with 0 and tituloP5 with blank field and Num_Slides 4
But If user choose to delete P3, tituloP3 I have to set P5 to 0 and tituloP5 to blank field SET P4 to 2 tituloP4 to Sometext5 and SET P3 to 5 tituloP3 to Sometext4 this way the information will be updated without P'gaps
I have this for cicle so far but dont work
if (isset($_POST['Confirmar'])){
$max = 5;
$menos1 = $max - 1;
for ($i = 4; $i >= 1; $i--){
$sqlya="SELECT P$i, tituloP$i FROM slider_settings where slider_settings.ID = 4";
for ($k = $menos1; $k <= $menos1; $k++){
$inserirya = "UPDATE slider_settings SET P$k ='P$i', tituloP$k ='tituloP$i' where slider_settings.ID = 4";
$con1 = $connect->query($sqlya);
$com2 = $connect->query($inserirya);
}
}
}
//This Will Provide U Update Query
function createUpdateString($position,&$str){
if($position==5){
return false;
}
$nextPosition = $position+1;
$str[] = " P{$position} = P{$nextPosition}";
$str[] = " tituloP{$position} = tituloP{$nextPosition}";
return createUpdateString($nextPosition,$str);
}
//Supose Your removing 3
//Update The p3 and tituloP3 values 0 and ""
$updatePostion = 3;
$str = array();
//This function will create query string for you
createUpdateString($updatePostion,$str);
$queryString = implode(",",$str);
if(!empty($queryString)){
$query = "UPDATE TABLE_NAME SET ".$queryString ."where slider_settings.ID = 4";
}

Mysql (PHP): delete all rows which SUM = 0

I have this table
+----+--------+
| id | amount |
+----+--------+
| 1 | 10 |
| 2 | 5 |
| 3 | -5 |
| 4 | 6 |
| 5 | -16 |
| 6 | 4 |
| 7 | 1 |
| 8 | -3 |
+----+--------+
I need to delete all rows (in order, from min ID to max ID) witch SUM = 0.
In my example, if we divide the table, I need to delete the id 1,2,3,4,5 because their SUM = 0 (10+5-5+6-16), but leave the record 6,7,8
I don't know how write the query, to read step to step the rows.
Thank you
DELETE a
FROM my_table a
JOIN
( SELECT x.*
, SUM(y.amount) running
FROM my_table x
JOIN my_table y
ON y.id <= x.id
GROUP
BY x.id
) b
ON b.id >= a.id
WHERE b.running = 0;
PHP-ish Pseudo code:
$data = get_data();
list($minID, $maxID, $currSum) = array($data[0]['id'], 0, 0);
foreach ( $data as $value ) {
$currSum += $value['amount'];
if ( !$currSum ) {
$maxID = $value['id'];
break;
}
}
$sql = "DELETE FROM table WHERE id >= $minID AND id <= $maxID";

update table from array with different values where empty field

I have problem with my code, problem is data not update still NULL.
table A
year | period | code | user_id
2013 | 4 | 1231 |
2013 | 4 | 1232 |
2013 | 4 | 1233 |
2013 | 4 | 1234 |
2013 | 4 | 1235 |
Table B
user_id | user_name | cash
A1 | AB | 10
A2 | BC | 5
A3 | CD | 7
I will put table B user_id to table A user_id when cash >= 7
Table Result
year | period | code | user_id
2013 | 4 | 1231 | 10
2013 | 4 | 1232 | 7
2013 | 4 | 1233 |
2013 | 4 | 1234 |
2013 | 4 | 1235 |
here my code,
$arr = array();
$query = mysql_query("select user_id from tableB where cash >= 7");
while ($arrs = mysql_fetch_array($query)) {
$arr[] = $arrs[0];
}
$count = count($arr);
for ($i = 0; $i < $count; $i++) {
$sql = mysql_query("UPDATE tableA SET user_id ='$arr[$i]' WHERE year = 2013 and period = 4 and user_id IS NULL");
}
if ($sql) {
echo "success";
}
The operator in the query should be >= and not =>
check on this:
$arr[] = $arrs[0];
this now holds the first record of the result set. Expected that there is only one record with cash >= 7, that might be ok, but thats a risky assumption.
for ($i = 0; $i < $count; $i++) {
$sql = mysql_query("UPDATE tableA SET user_id ='$arr[$i]' WHERE year = 2013 and
period = 4 and user_id IS NULL");
}
in here $arr[$i] iterates over the fields of the first record, giving you in a sequence the values 'A3', 'CD' and 7 and you are running three useless updates on your table. Afterwards the column user_id in Table A has the value 7 and not 'A3' since this is the last value in your loop.
I have solution for my code,
$arr = array();
$query = mysql_query("select user_id from tableB where cash >= 7");
while ($arrs = mysql_fetch_array($query)) {
$arr[] = $arrs[0];
}
$q = mysql_query("select code from tableA order by code");
$index = 0;
while($codes = mysql_fetch_row($q)){
$sql = mysql_query("UPDATE tableA SET user_id ='".$arr[$index++]."' WHERE code='".$codes[0]."'");
}
result perfect !
thanks all

Check sentences if have same words

tb_content(left) and tb_word(right) :
===================================== ================================
|id|sentence |sentence_id|content_id| |id|word|sentence_id|content_id|
===================================== ================================
| 1|sentence1| 0 | 1 | | 1| a | 0 | 1 |
| 2|sentence2| 1 | 1 | | 2| b | 0 | 1 |
| 3|sentence5| 0 | 2 | | 3| c | 1 | 1 |
| 4|sentence6| 1 | 2 | | 4| a | 1 | 1 |
| 5|sentence7| 2 | 2 | | 5| e | 1 | 1 |
===================================== | 6| f | 0 | 2 |
| 7| g | 1 | 2 |
| 8| h | 1 | 2 |
| 9| i | 1 | 2 |
|10| f | 2 | 2 |
|11| h | 2 | 2 |
|12| f | 2 | 2 |
================================
I need to check if every sentence consist of words that owned by other sentences in every content_id.
for example :
Check for the content_id = 1 they are sentence1 and sentence2. from tb_word, we can see that sentence1 and sentence2 consist of the same word a. if the number of a in two sentences is >=2, then a will be the result. So if I print the result, it must be :
00Array ( [0] => a [1] => b) 01Array ( [3] => a ) 10Array ( [3] => a )11Array ( [0] => c [1] => a [2] => e) where 00 means sentence_id = 0 and sentence_id = 0
first, I make functionTotal to count how many sentence that owned by every content_id :
$total = array();
$sql = mysql_query('select content_id, count(*) as RowAmount
from tb_content Group By contente_id') or die(mysql_error());
while ($row = mysql_fetch_array($sql)) {
$total[] = $row['RowAmount'];
}
return $total;
From that function I get the value of $total and from that I need to check the similarity of some words (from tb_word) between all the possibilities of 2 sentence
foreach ($total as $content_id => $totals){
for ($x=0; $x <= ($totals-1); $x++) {
for ($y=0; $y <= ($totals-1); $y++) {
$shared = getShared($x, $y);
}
}
the function of getShared is :
function getShared ($x, $y){
$token = array();
$shared = array();
$i = 0;
if ($x == $y) {
$query = mysql_query("SELECT word FROM `tb_word`
WHERE sentence_id ='$x' ");
while ($row = mysql_fetch_array($query)) {
$shared[$i] = $row['word'];
$i++;
}
} else {
$query = mysql_query("SELECT word, count(word) as jml
FROM `tb_word` WHERE sentence_id ='$x'
OR sentence_id ='$y'
GROUP BY word ");
while ($row = mysql_fetch_array($query)) {
$jml = $row['jml'];
$token[$i] = $row['word'];
if ($jml >= 2) {
$shared[$i] = $token[$i];
}
$i++;
}
But the result I get is still wrong. the result still mix between different content_id. the result must be group by content_id also. sorry for my bad english and my bad explanation. cmiiw, please help me.. thank you :)
This one can be actually done by DBMS itself, two steps in one query. First, you make a self join in order to prepare sentence combinations within the same content:
SELECT a.content_id,
a.sentence_id AS sentence_id_1,
b.sentence_id AS sentence_id_2
FROM tb_content AS a
JOIN tb_content AS b
ON ( a.content_id = b.content_id
AND a.sentence_id <= b.sentence_id )
The "<=" will keep same sentence joins, like "1-1" or "2-2", and yet avoid bidirectional repetitions, like "1-2" and "2-1". Next you can join the above result with words and count the number of occurances. Like that:
SELECT s.content_id,
s.sentence_id_1,
s.sentence_id_2,
c.word,
Count(*) AS jml
FROM (SELECT a.content_id,
a.sentence_id AS sentence_id_1,
b.sentence_id AS sentence_id_2
FROM tb_content AS a
JOIN tb_content AS b
ON ( a.content_id = b.content_id
AND a.sentence_id <= b.sentence_id )) AS s
JOIN tb_word AS c
ON ( s.content_id = c.content_id
AND ( c.sentence_id = s.sentence_id_1
OR c.sentence_id = s.sentence_id_2 ) )
GROUP BY s.content_id,
s.sentence_id_1,
s.sentence_id_2,
c.word
HAVING Count(*) >= 2;
The result of the above query will give you the container, sentences 1 and 2, the word, and the number of occurances (which is 2 or more). All you need now is collecting the result into the array which as I see you already know to do.
Let me know, if I missunderstood your goal.
How about simply SELECT content_id, word, COUNT(*) as num_appearing FROM tb_word GROUP BY content_id, word?
EDIT: I see the complexity now: your main issue is that the getShared() function has two sentence IDs passed to it, but no content_id to know which content is being analyzed. You're also assuming that content_id and sentence_id numbers are consecutive and start at zero. My code doesn't assume that, and pulls those IDs directly from the database.
<?php
$rs = mysql_query("SELECT * FROM tb_content");
$content = array();
while ($row = mysql_fetch_assoc($rs)) {
if (!isset($content[$row['content_id']])) $content[$row['content_id']] = array();
$content[$row['content_id']][] = $row['sentence_id'];
}
foreach($content as $content_id => $sentences) {
foreach($sentences as $sentence_id) {
foreach($sentences as $compare) {
$shared = getShared($content_id, $sentence_id, $compare);
}
}
}
function getShared($cid, $s1, $s2) {
$rs = mysql_query("SELECT `word`, COUNT(*) AS 'num' FROM `tb_word` WHERE `content_id`={$cid} AND `sentence_id` IN ({$s1}, {$s2}) GROUP BY `word`");
$out = array();
while ($row = mysql_fetch_assoc($rs)) {
if ($rs['num'] >= 2) $out[$rs['word']] = $rs['num'];
}
return $out;
}

get the column name where the data was found in MySQL

is it possible to get the Column name where a particulare data was found without looping through the result, maybe by PDO? or is there another way to do this in mySQL?
the example show only 3 columns but for my table i may have up to 30 columns need to be check
if i have a table, table1 and want to find the column(s) where 'x' was found
+----+------+------+------+
| id | Col1 | Col2 | Col3 |
+----+------+------+------+
| 0 | x | b | x |
| 1 | x | x | f |
| 2 | d | x | g |
| 3 | h | j | k |
+----+------+------+------+
currentyl i run a Select then loop to each row and check each row column if data is 'x'
$query= "SELECT * FROM table1 WHERE (Col1='x' OR Col2='x' OR Col3='x')"
$result=mysql_query($query);
$foundCols = array();
$rowCnt = 0;
while ($row = mysql_fetch_assoc($result)) {
$tmpArr = array();
if ($row['Col1'] == 'x') {
$tmpArr[] = 'Col1';
}
if ($row['Col2'] == 'x') {
$tmpArr[] = 'Col2';
}
if ($row['Col3'] == 'x') {
$tmpArr[] = 'Col3';
}
$foundCols[$rowCnt] = $tmpArr;
$rowCnt = $rowCnt+1
}
thank you
Try this:
while ($row = mysql_fetch_assoc($result)) {
...
foreach (array('Col1', 'Col2', 'Col3') as $key) {
if ($row[$key] == 'x') {
$tmpArr[] = $key;
}
}
...
}

Categories