Here's some code adapted from phpBB. Near as I can tell it's trying to delete all topics wherein the only poster is the target user.
(note that for testing purposes I changed the final query from a DELETE to a SELECT)
<?php
$user_id = 66275;
mysql_connect('localhost', 'username', 'password');
mysql_select_db('db_name');
$start = microtime(true);
$total = 0;
define('POSTS_TABLE', 'phpbb_posts');
define('TOPICS_TABLE', 'phpbb_topics');
$sql = 'SELECT topic_id, COUNT(post_id) AS total_posts
FROM ' . POSTS_TABLE . "
WHERE poster_id = $user_id
GROUP BY topic_id";
$result = mysql_query($sql);
$topic_id_ary = array();
while ($row = mysql_fetch_assoc($result))
{
$topic_id_ary[$row['topic_id']] = $row['total_posts'];
}
mysql_free_result($result);
if (sizeof($topic_id_ary))
{
$sql = 'SELECT topic_id, topic_replies, topic_replies_real
FROM ' . TOPICS_TABLE . '
WHERE ' . sql_in_set('topic_id', array_keys($topic_id_ary));
$result = mysql_query($sql);
$del_topic_ary = array();
while ($row = mysql_fetch_assoc($result))
{
if (max($row['topic_replies'], $row['topic_replies_real']) + 1 == $topic_id_ary[$row['topic_id']])
{
$del_topic_ary[] = $row['topic_id'];
}
}
mysql_free_result($result);
if (sizeof($del_topic_ary))
{
$sql = 'SELECT topic_id FROM ' . TOPICS_TABLE . '
WHERE ' . sql_in_set('topic_id', $del_topic_ary);
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result))
{
$total++;
echo $row[topic_id] . "\r\n";
}
}
}
function sql_in_set($field, $array, $negate = false, $allow_empty_set = false)
{
if (!sizeof($array))
{
if (!$allow_empty_set)
{
// Print the backtrace to help identifying the location of the problematic code
$this->sql_error('No values specified for SQL IN comparison');
}
else
{
// NOT IN () actually means everything so use a tautology
if ($negate)
{
return '1=1';
}
// IN () actually means nothing so use a contradiction
else
{
return '1=0';
}
}
}
if (!is_array($array))
{
$array = array($array);
}
if (sizeof($array) == 1)
{
#reset($array);
$var = current($array);
return $field . ($negate ? ' <> ' : ' = ') . $var;
}
else
{
return $field . ($negate ? ' NOT IN ' : ' IN ') . '(' . implode(', ', $array) . ')';
}
}
$elapsed = microtime(true) - $start;
echo "\r\ntook $elapsed seconds";
echo "\r\ngot $total rows back";
?>
This does three queries. First gets all the topics the target user has posted in and the number of times they've posted in each topic. The second gets how many replies each topic in the first query actually has. Then there's some PHP code to see which topics have had all their posts made by the target user. After that the code (prior to my changes) DELETEs all those topics.
Overall it seems to me that this could be written better by doing something like this:
SELECT t.topic_id
FROM phpbb_topics AS t
JOIN phpbb_posts AS p1
ON p1.topic_id = t.topic_id
AND p1.poster_id = $poster_id
LEFT JOIN phpbb_posts AS p2
ON p2.topic_id = t.topic_id
AND p2.poster_id <> $poster_id
WHERE p2.poster_id IS NULL;
Or maybe this:
SELECT t.topic_id
FROM phpbb_topics AS t
JOIN phpbb_posts AS p1
ON p1.topic_id = t.topic_id
AND p1.poster_id = $poster_id
AND t.topic_poster = $poster_id
AND t.topic_last_poster_id = $poster_id
LEFT JOIN phpbb_posts AS p2
ON p2.topic_id = t.topic_id
AND p2.poster_id <> $poster_id
WHERE p2.poster_id IS NULL
Testing this is actually quite difficult thanks to MySQLs caching but... from what testing I have been able to do it seems like the way phpBB is currently doing it is in fact faster. Which is surprising to me.
Any ideas?
It looks to me like you are on the right track. Try adding indexes to all the columns you are using in the joins as this can often drastically increase the speed of joins.
Related
I have two tables webadstats and webstatsclick and i want to make below query from these two tables.
$sql2 = "SELECT
count(*) as 'impressions',
unix_timestamp(date(from_unixtime(A.time))) as 'timestamp',
COUNT(B.click) as 'clickss'
FROM `webadstats` as A
LEFT JOIN `webstatsclick` as B
ON A.pubadhash = B.pubadhash
WHERE A.pubadhash='$pubadhash'
GROUP BY date(from_unixtime(A.time))";
$result2 = mysqli_query($conn, $sql2);
if (mysqli_num_rows($result2)>0) {
while($row = mysqli_fetch_assoc($result2)) {
$impressions[] = $row['impressions'];
$clicksall[] = $row['clickss'];
$timestamp[] = $row['timestamp'];
}
for($i=0; $i<count($clicksall); $i++){
$str .= $timestamp[$i] . '||' . $impressions[$i] . '||' . $clicksall[$i] ."\n";
}
}
echo $str;
But the problem is that this query is generating same values for both the variables impressions and clickss out of which value of impressions variable is correct.
1542434400||1270||1270
1542520800||1800||1800
1542607200||1745||1745
1542693600||1805||1805
1542780000||1615||1615
1542866400||1740||1740
1542952800||1740||1740
1543039200||1830||1830
1543125600||1830||1830
1543212000||1615||1615
1543298400||1880||1880
1543384800||2125||2125
1543471200||1530||1530
1543557600||1370||1370
1543644000||120||120
My both the DB structure is
webadstats db
webadstats db
webstatsclick db
webstatsclick db
Kindly help me where i am wrong.
Let's go back to the two query approach. The problem is, we've been trying to use JOIN on pubadhash but also WHERE with pubadhash, so the values get multiplied.
$sql2 = "SELECT
count(*) as 'impressions',
unix_timestamp(date(from_unixtime(time))) as 'timestamp'
FROM `webadstats`
WHERE pubadhash='$pubadhash'
GROUP BY date(from_unixtime(time))";
$sql3 = "SELECT
count(*) as 'clickss',
unix_timestamp(date(from_unixtime(time))) as 'timestamp'
FROM `webstatsclick`
WHERE pubadhash='$pubadhash'
GROUP BY date(from_unixtime(time))";
$result2 = mysqli_query($conn, $sql2);
if (mysqli_num_rows($result2)>0) {
while($row = mysqli_fetch_assoc($result2)) {
$arr[$row['timestamp']]['impressions'] = $row['impressions'];
$arr[$row['timestamp']]['timestamp'] = $row['timestamp'];
$arr[$row['timestamp']]['clickss'] = 0;
}
$result3 = mysqli_query($conn, $sql3);
if (mysqli_num_rows($result3)>0) {
while($row = mysqli_fetch_assoc($result3)) {
$arr[$row['timestamp']]['clickss'] = $row['clickss'];
}
}
foreach($arr as $clicks){
$str .= $clicks['timestamp'] . '||' . $clicks['impressions'] . '||' . $clicks['clickss'] ."\n";
}
}
echo $str;
I'm trying to sum my MySQL column value with number, here is my php script, i dont think im doing in right way. I was searching in stackoweflow but i havent found how to sum with specific number, not with other column.
<?php
$currentUser = isset($_POST['currentUser']) ? $_POST['currentUser'] : '';
$currentTasken = isset($_POST['currentTasken']) ? $_POST['currentTasken'] : '';
$con = mysql_connect("localhost", "root", "") or die(mysql_error());
if(!$con)
die('Could not connectzzz: ' . mysql_error());
mysql_select_db("foxi" , $con) or die ("could not load the database" . mysql_error());
$check = mysql_query("SELECT * FROM dotp_task_log");
$numrows = mysql_num_rows($check);
if($numrows >= 1)
{
//$pass = md5($pass);
$ins = mysql_query("INSERT INTO dotp_task_log (task_log_creator, task_log_Task) VALUES ('$currentUser' , '$currentTasken')" ) ;
if($ins)
$check = mysql_query("SELECT * FROM dotp_task WHERE task_id='$currentTasken'");
$numrows = mysql_num_rows($check);
if($numrows == 1)
{
//$pass = md5($pass);
$ins = mysql_query("SELECT (SELECT SUM(task_percent_complete) FROM dotp_task WHERE task_id='$currentTasken') FirstSum, (SELECT SUM(5)), SecondSum ");
if($ins)
die("Succesfully summed!");
else
die("ERROR");
}
else
{
die("Cant sum!");
}
die("Succesfully Created Log!");
else
die("ERROR");
}
else
{
die("Log already exists!");
}
?>
Your query is not written properly. Try to run this query from MySQL command line or from PHPMyAdmin. It will give you an idea what the error is. My best guess is that the first part of the query is not complete.
This is what it will resolve to
SELECT n FirstSum, 5, SecondSum
Where n is the value returned from the subquery. This is a syntax error. Try to remove the last comma before SecondSum.
This is what your query should be:
SELECT (SELECT Sum(task_percent_complete)
FROM dotp_task
WHERE task_id = '$currentTasken') FirstSum,
(SELECT Sum(5)) SecondSum
remove
(select sum(5))
and replace it with
(select 5)
I want my query like this:
SELECT tbl_bids. * , tbl_department.vDeptName, tbl_user.vFirst
FROM tbl_bids
LEFT JOIN tbl_bids_department ON tbl_bids_department.iBidID = tbl_bids.iBidID
LEFT JOIN tbl_department ON tbl_department.iDepartmentID = tbl_bids_department.iDepartmentID
LEFT JOIN tbl_user ON tbl_user.iUserID = tbl_bids.iUserID
WHERE tbl_user.iUserID = '1' // with parantheses in where clause
AND (
tbl_department.vDeptName = 'PHP'
OR tbl_department.vDeptName = 'android'
)
GROUP BY tbl_bids.iBidID
ORDER BY iBidID DESC
LIMIT 0 , 30
But i can't find the way to get parantheses in my query,there are mutiple condition and loop will be there to make where clause..
here is my code
$select = $this->tableGateway->getSql()->select();
$select->columns(array('*'))
->join('tbl_bids_department', 'tbl_bids_department.iBidID = tbl_bids.iBidID', array(),"LEFT")
->join('tbl_department', 'tbl_department.iDepartmentID = tbl_bids_department.iDepartmentID',array(tbl_department.vDeptName),"LEFT")
->join('tbl_user', 'tbl_user.iUserID = tbl_bids.iUserID',array(tbl_user),"LEFT")
->group('tbl_bids.iBidID');
$where = new \Zend\Db\Sql\Where();
$where->equalTo( 'tbl_bids.eDeleted', '0' );
$sWhere = new \Zend\Db\Sql\Where();
for ( $i=0 ; $i<count($aColumns) ; $i++ )
{
if (isset($data['sSearch_'.$i]) && $data['sSearch_'.$i] != "")
{
if($aColumns[$i] == 'vDeptName'){
$allDept = explode(',', $data['sSearch_'.$i]);
foreach ($allDept as $key => $value) {
if($key == 0)
$sWhere->AND->equalTo("tbl_department.vDeptName", $value);
else
$sWhere->OR->equalTo("tbl_department.vDeptName", $value);
}
}elseif($aColumns[$i] == 'vFirst')
$sWhere->AND->equalTo("tbl_user.iUserID",$data['sSearch_'.$i]);
else
$sWhere->AND->like("tbl_bids.".$aColumns[$i], "%" . $data['sSearch_'.$i] . "%");
$select->where($sWhere); // here my where clause is create
}
}
//var_dump($select->getSqlString());
$resultSet = $this->tableGateway->selectWith($select);
return $resultSet;
}
I have others many fields to pass through where which also have same problem of paratheses
if there is no any condition i can use nest() and unnest() predicate , but it will show me that string is not nested error,
So pls help me to find the solution.
Pls attach example with solution.
here is a short example
$where = new Sql\Where();
$where->equalTo('col',thirdVal')
->NEST //start braket
->equalTo('col','someVal')
->OR
->equalTo('col','secondVal')
->UNNEST //close bracet
hope this will help
I'm trying to figure out how to build a query using Yii's CDbCriteria that would be equivalent to the following:
SELECT
*
FROM
user u
JOIN (
SELECT *
FROM skill_assessment s
WHERE s.skill = 'HTML'
AND s.score >= 80
) b ON
(u.id = b.userId)
JOIN (
SELECT *
FROM skill_assessment s
WHERE s.skill = 'CSS3'
AND s.score >= 80
) c ON
(u.id = c.userId);
etc...
Here's what I have so far, that isn't working:
$criteria = new CDbCriteria();
$criteria->alias = "u";
$criteria->select = "*";
$criteria->join = "JOIN skill_assessment s ON (u.id=s.userId)";
for($i = 0; $i < count($skill_filters); $i++) {
$criteria->addCondition("s.skill='".$skill_filters[$i]->skill."' AND s.score >= ".$skill_filters[$i]->level);
}
$users = UserModel::model()->findAll($criteria);
Any help would be greatly appreciated.
Thanks in advance.
EDIT:
I was able to build out the sql query as a string and use findAllBySql, which returned the correct UserModels that matched my search criteria, the problem is that I haven't been able to get it to return the related SkillAssessmentModels. They don't come back either with the initial query, like this:
$users = UserModel::model()->with('skill_assessments')->findAllBySql($sql);
nor if I get the results like this:
$users = UserModel::model->findAllBySql($sql);
foreach($users as $user)
{
$user->skill_assessments = $user->getRelated('skill_assessments');
}
Any thoughts on how I can get those related models?
The strange thing is that elsewhere in my application, I CAN get the related models if I do this:
$user = UserModel::model->findByPk($id);
$user->skill_assessments->getRelated('skill_assessments');
Second param for addCondition is by default 'AND'. Is this what you are looking for? May be you should define 'OR' for $operator and add braces around condition.
But in your case addCondition will by applied to the user table, not to the JOIN.
I think that this should work for you:
$criteria = new CDbCriteria();
$criteria->alias = "u";
$criteria->together= "skill_assessment";
$where = array();
for($i = 0; $i < count($skill_filters); $i++) {
$where[] = "(s.skill='".$skill_filters[$i]->skill."' AND s.score >= ".$skill_filters[$i]->level . ')';
}
$criteria->join = 'JOIN skill_assessment s ON (u.id=s.userId' . ( $where ? ( ' AND (' . join( ' OR ', $where ) . ')' ) : '') . ')';
$users = UserModel::model()->findAll($criteria);
Fetch _skill_assessment_ like this:
foreach( $users->skill_assessment as $skill_assessment )
{
echo $skill_assessment->userId;
}
At this level keep it simple:
$sql="select * from mytable where id = :id";
$cmd = Yii::app()->db->createCommand($sql)->bindParam("id", $res_id);
$cmd->execute();
Thanks a lot to Boris Belenski!
What you suggested wasn't quite what I needed, but it did get me to what I needed. Here is what I ended up with that works:
$str = "abcdefghijklmnopqrstuvwxyz";
$idxs = str_split($str);
$criteria = new CDbCriteria();
$criteria->alias = "u";
$joins = array();
for($i = 0; $i < count($skill_filters); $i++)
{
$joins[] = " JOIN (SELECT * FROM skill_assessment s WHERE s.skill = '" . $skill_filters[$i]->skill ."' AND s.score >= " . $skill_filters[$i]->level . ") " . $idxs[$i] . " ON (u.id = " . $idxs[$i] . ".userId) ";
}
$criteria->join = join(' ', $joins);
$users = UserModel::model()->findAll($criteria);
foreach($users as $user)
{
$user->skill_assessments = $user->getRelated('skill_assessments');
}
The really key part is that $joins array.
This will allow you to get all the users that match ALL the criteria for row matches in the skill_assessments table.
Also, I could probably lazily load the skill assessments in the View in a normal view, but I need to get all the skill_assessments for each user now in order to pass them back in an ajax response with the user.
So I have following as part of my query
SELECT * FROM $table WHERE columname LIKE '%$searchterm%'
I have tried taking out leading and/or ending wildcards meaning
SELECT * FROM $table WHERE columname LIKE '$searchterm%'
AND
SELECT * FROM $table WHERE columname LIKE '%$searchterm'
AND
SELECT * FROM $table WHERE columname LIKE '%$searchterm%' OR columname LIKE '$searchterm'
and also tried adding following to the query with no luck
OR columname = '$searchterm'
So when my search term is "myval" and if column has whole string "myval", I would like to have that selected. But ALL of my queries above, return false/return nothing where myval is searchterm and column value as full.
I can not use MATCH because this is not Full-Text index.
EDIT:
PHP Code:
$sterm = NULL;
$table = 'mytable';
if(isset($_GET['s'])) { $sterm = explode(" ", mysql_real_escape_string($_GET['s'])); }
if(isset($_POST['s'])) { $sterm = explode(" ", mysql_real_escape_string($_POST['s'])); }
if(!empty($sterm)){
$getdata = "SELECT * FROM $table WHERE termsi != 'Special' ";
foreach ($sterm as $value){
$getdata .= "AND netid_all LIKE '%$value%' OR netid_all = '$value' ";
} //End foreach
$getdata .= "LIMIT 10";
$result = mysql_query($getdata) or die(mysql_error());
$row = mysql_fetch_array($result, MYSQL_ASSOC);
while($row = mysql_fetch_array($result, MYSQL_ASSOC))
{
echo <<<PRINTALL
{$row[0]}, {$row[1]}, {$row[2]}, {$row[3]}, {$row[4]}, {$row[5]}, {$row[6]}, {$row[7]}, ' <br />'
PRINTALL;
} //End While
} //End If search exists
Okay So As you guys suggested, i tried PHPMyAdmin sql console and it works fine, so it would have to be by PHP!? so here it is.
I'd suggest writing your query building like this:
$fullvalues = array();
$partials = array();
foreach ($sterm as $value){
$partials[] = "(netid_all LIKE '%" . mysql_real_escape_string($value) . "%')";
$fullvalues[] = "'" . mysql_real_escape_string($value) . "'";
}
$partials = implode(' OR ', $partials);
$fullvalues = implode(', ', $fullvalues);
$sql = <<<EOL
SELECT *
FROM $table
WHERE (termsi != 'Special')
AND (($partials) OR (netid_all IN ($fullvalues));
EOL;
Assuming your search string is a b c, you'd get this query:
SELECT *
FROM yourtable
WHERE (termsi != 'Special')
AND (((netid_all LIKE '%a%') OR (netid_all LIKE '%b%') OR (netid_all LIKE '%C%')) OR (netid_all IN ('a', 'b', 'c')))
If your search requires that all terms be present, then change the 'OR' to 'AND' in the implode.
Well found it,
$row = mysql_fetch_array($result, MYSQL_ASSOC);
while($row = mysql_fetch_array($result, MYSQL_ASSOC))
Was the problem, earlier when I was testing things, anyhow, it should have been the following
$row = mysql_fetch_array($result, MYSQL_ASSOC);
while($row)