MySql variables and php - php

I am getting an error with this in php. What is the correct way to format this string to pass to mysql_query() in php?
SELECT count(*) FROM agents INTO #AgentCount;
SELECT user_agent_parsed, user_agent_original, COUNT( user_agent_parsed ) AS thecount,
COUNT( * ) / ( #AgentCount) AS percentage
FROM agents
GROUP BY user_agent_parsed
ORDER BY thecount DESC LIMIT 50;
In php, here is how I set up the $query
$query = "
SELECT count(*) FROM agents INTO #AgentCount;
SELECT user_agent_parsed, user_agent_original, COUNT( user_agent_parsed ) AS thecount,
COUNT( * ) / ( #AgentCount) AS percentage
FROM agents
GROUP BY user_agent_parsed
ORDER BY thecount DESC LIMIT 50";
That exact query will work fine if I put it directly into MySql via a command line session. Do I need to issue two separate php calls to mysql_query() and store the first result?
I am getting the below error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT user_agent_parsed, user_agent_original, COUNT( user_agent_parsed ) AS thecount' at line 3
The reason for not using a sub select and instead choosing a MySql variable is to avoid a count() happening on every percentage calculation. Though it may be possible the engine is optimizing for that. So far, I have not been able to confirm that. I have also heard sub selects are almost always non optimal.
EXPLAIN tells me this:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY agents index NULL user_agent_parsed 28 NULL 82900 Using temporary; Using filesort
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away

You can only have one query at a time in PHP.
$query1 = "SELECT count(*) FROM agents INTO #AgentCount"
$query2="
SELECT user_agent_parsed, user_agent_original, COUNT( user_agent_parsed ) AS thecount,
COUNT( * ) / ( #AgentCount) AS percentage
FROM agents
GROUP BY user_agent_parsed
ORDER BY thecount DESC LIMIT 50";
UPDATE
I have a DAL that contains all my queries. A typical function in my DAL looks like this:
// These functions are reusable
public function getAllRows($table)
{
$sql =" SELECT * FROM $table";
$this->query($sql);
return $this->query_result;
}
Then in my BLL (Business Layer) I have the following:
public function getUserAgents()
{
$result = parent::getAllRows();
$row = mysql_fetch_array($result);
return $row[0]; // Retrieves the first row
// Then you take this value and to a second request. Then return the answer / rows.
}

If you are using mysql_query, then yes, you need to send each query separately. From the description at the top of mysql_query's entry in the PHP manual: "mysql_query() sends a unique query (multiple queries are not supported) to the currently active database..."
As for subqueries, you'd be surprised; the query optimizer generally handles them very well.

Related

What PDO query should i use?

I have a table on my database which called topics(topic_id,topic_subject,topic_content,topic_date,topic_cat,topic_comm,topic_by,votes,tags,views,flags), from this table i want to echo
10 top users(topic_by) with the most topics(max number of topics) on a specific community(topic_comm). What PDO query should i use ? I think need something like below:
$sql = $conn -> prepare("SELECT topic_by WHERE topic_comm=:comm AND ( MAX COUNT(topic_id) )")
Let construct the query step by step. In order to get the top 10 user by most topic by community, you need to compute number of topic by each user on that community.
SELECT topic_by, COUNT(*) AS total_topic FROM topic
WHERE topic_comm = :comm GROUP BY topic_by
Then, you want to get the top 10 user, you can use basic subquery and LIMIT. So the final query
SELECT * FROM (
SELECT topic_by, COUNT(*) AS total_topic FROM topic
WHERE topic_comm = :comm GROUP BY topic_by
) AS t ORDER BY t.total_topic DESC LIMIT 10

Mysql query returns error #1093 - You can't specify target table

I need to check and update with same query my database.
The error says it is not possble to update same table which is included in the select statement. Is there any workaround of this to happen in 1 mysql query? Here is the query:
$query='update option_values_to_products set available="0" where id in (
select ovtp.id from option_values ov,option_values_to_products ovtp,options o where
ovtp.product_id="1657" and ovtp.option_values_id=ov.id and ov.options_id=o.id and
o.name="Size" group by ovtp.id )';
Yes, this is a nagging feature of mysql and there is a workaround to it: wrap the subquery within the IN() clause into another subquery.
update option_values_to_products set available="0" where id in (select id from (
select ovtp.id from option_values ov,option_values_to_products ovtp,options o where
ovtp.product_id="1657" and ovtp.option_values_id=ov.id and ov.options_id=o.id and
o.name="Size" group by ovtp.id ) as t)
Avoid using nested queries for many reasons like performance and memory issue, also it can be very hard to be understood for the next developers
Good practice Split your query into 2 parts :
<?php
$qSelect = 'select ovtp.id from option_values ov,option_values_to_products ovtp,options o where
ovtp.product_id="1657" and ovtp.option_values_id=ov.id and ov.options_id=o.id and
o.name="Size" group by ovtp.id';
$res = DATABASE_MANAGER::exec($qSelect);
$qUpdate = 'update option_values_to_products set available="0" where id in (' . implode(",", $res) .')';
$res2 = DATABASE_MANAGER::exec($qUpdate);

Did I mess up my where clause? Getting unexpected results

$active_sth = $dbh->prepare("SELECT * FROM user_campaign
WHERE status='blasting'
OR status='ready'
OR status='followup_hold'
OR status='initial_hold'
AND uid=:uid
ORDER BY status ASC");
$active_sth->bindParam(':uid', $_SESSION['uid']['id']);
$active_sth->execute();
I am positive $_SESSION['uid']['id'] = 7
but it will also pull results of id 10 or any other number.
Is my AND/OR clause written wrong?
Yes, query is wrong
SELECT * FROM user_campaign
WHERE (
status='blasting'
OR status='ready'
OR status='followup_hold'
OR status='initial_hold'
)
AND uid=:uid
ORDER BY status ASC
You have to group all ORs to make sure that row got one of this values, and separately check if it have given uid.
The proper way to write that is:
SELECT * FROM user_campaign
WHERE status IN ('blasting', 'ready', 'followup_hold', 'initial_hold')
AND uid =: uid
ORDER BY status ASC
You should use IN instead of that huge amount of ORs :)

Speeding up MySQL query searching multiple tables using MATCH AGAINST

This is my first time trying to build more complex search functionality than just using the LIKE function. The results returned are pretty much perfect from this search but it's running really slow. Is there anything I can improve code wise to speed things up or anything I should look at on the database? or would I need to be looking at more server power?
Thanks a lot of any and all help. It's much appreciated!
function new_live_search($q){
$title_score = 5;
$tags_score = 10;
$upvote_score = 1;
$subdomain = $this->config->item('subdomain_name');
$query = "SELECT DISTINCT results.*,
(
".$title_score."*(MATCH(title) AGAINST('$q' IN BOOLEAN MODE)) +
".$tags_score."*(MATCH(tags.name) AGAINST('$q' IN BOOLEAN MODE)) +
".$upvote_score."*usefulness
) AS score
FROM results
LEFT JOIN tags ON results.id = tags.result_id
WHERE (scope = 'all' OR scope = '$subdomain')
AND (published = 1)";
$query .= "
HAVING score - usefulness > 0
ORDER BY score DESC, title";
$query = $this->db->query($query);
$results = array();
foreach ($query->result() as $row){
$results[] = $row;
}
return $results;
}
From MySQL documentation
Unfortunately it is not possible to combine Fulltext field and normal (i.e integer) field into one index. Since only one index per query can be used, that seems be a problem
Table layout:
id(integer primary key)|content(text fulltext indexed)|status(integer key)
Note that executing following query, MySQL will use only one index. Either fulltext, or status (Depending on intern statistics).
Query 1:
SELECT * FROM table WHERE MATCH(content) AGAINST('searchQuery') AND status = 1
However it is still possible to use both indexes in one query. You will need a new index on id,status pair and use join. Thus MySQL will be able to use one index for each table.
Query 2:
SELECT t1.* FROM table t1
LEFT JOIN table t2 ON(t1.id=t2.id)
WHERE MATCH(t1.content) AGAINST('searchQuery') AND status=1
Query 2 will run significantly faster than Query 1, at least in my case :)
Note the overhead: You will need an id for each row and a key which is spanned over needed fields starting with id.
Refer Fulltext search on MySQL Documentation
Hope it help you
If you look at your query, your fulltext part of the query does not actually limit the search. Using something like the following should increase performance a bit.
SELECT DISTINCT results.*, (
$title_score * (MATCH(title) AGAINST('$q' IN BOOLEAN MODE)) +
$tags_score * (MATCH(tags.name) AGAINST('$q' IN BOOLEAN MODE)) +
$upvote_score * usefulness
) AS score
FROM results
LEFT JOIN tags ON results.id = tags.result_id
WHERE (scope = 'all' OR scope = '$subdomain')
AND (published = 1)
AND (
(MATCH(title) AGAINST('$q' IN BOOLEAN MODE)) OR
(MATCH(tags.name) AGAINST('$q' IN BOOLEAN MODE)))
HAVING score - usefulness > 0
ORDER BY score DESC, title

MYSQL: Help with a left join? Might be better as two queries?

Im not to versed in mysql JOINS, but I think that is what is required for what I am trying to do.
With the help of SO, I got this excellent piece of SQL for calculating a count of items in my database (by categories):
SELECT SUM(`tid` IS NULL) AS `total_null`,
SUM(`tid` = 0) AS `total_zero`,
COUNT(DISTINCT `tid`) AS `other`
FROM `mark_list`
WHERE `user_id` = $userid
Now what I need the query to do is check another table: mark_options to see if the value groupthem = 1. If groupthem = 1 then the above query should be used. If groupthem = 0 then I would like to use the following query:
SELECT tid,
COUNT(*) AS other
FROM mark_list
WHERE userid = $userid
Is it better to run 2 queries, the first one to check if groupthem = 1 or 0, then have PHP decide which final query to run, or to use an SQL JOIN (or other method) to do the same function in a single query?
Thanks!!
Plz send teh reps. Kthx bai.
SELECT SUM(`mark_list`.`tid` IS NULL) AS `total_null`,
SUM(`mark_list`.`tid` = 0) AS `total_zero`,
COUNT(DISTINCT `mark_list`.`tid`) AS `other`,
COUNT(`mark_list`.`tid`) AS `ungrouped`,
`mark_options`.`groupthem`
FROM `mark_list`, `mark_options`
WHERE `mark_list`.`user_id` = $userid
GROUP BY `mark_options`.`groupthem`

Categories