Since a while I am trying to remove the quotes of my mysql query in a ZF2 application. I need to remove the quotes to make this query works, testing the query over command line succeeded by removing the quotes around GEODIST().
$adapter = $serviceLocator->get('SphinxSearch\Db\Adapter\Adapter');
$sql = new Sql($adapter);
$select = new Select;
$select ->columns(array('*', 'distance' => 'GEODIST(23.3556740442177, 2.9525189115381, latitude, longitude)'))
->from('table_name')
->where(array('distance > ?' => 250000))
->order('distance ASC')
->limit(25);
echo $select->getSqlString(new SphinxQL());
Outputs
SELECT *, `GEODIST(23.3556740442177, 2.9525189115381, latitude, longitude)` AS `distance` FROM `table_name` ORDER BY `distance` ASC LIMIT 0,25
I've found the follow solution to make this work by resetting the query with a simple replacer.
$statement = $sql->prepareStatementForSqlObject($select);
$statement ->setSql(str_replace('`', '', $statement->getSql()));
This did the job for me.
Related
I have some problems/doubt with PDO statement and Yii2 query.
I've search and read some question here but i didn't find a solution.
So i have an array like this
array (size=3)
0 => string '12345'
1 => string '6789'
2 => string '101258'
From this array i create a string to insert in my IN condition for SQL query
//$split_var is the previous array
$var_query = implode( "','" , $split_var);
//'12345','6789','101258' i obtained this string
So now I try to create a query like this way
$tupla = Yii::$app->db->createCommand("
SELECT * FROM oln, opt WHERE opt_cod = oln_opt_cod AND oln_cod IN ( :var_query) order by oln_cod ASC
")
->bindValue(':var_query' ,$var_query);
$result = $tupla->queryAll();
It doesn't give me any error but the resulted query isn't what I'm expected. In fact I'll get that query:
SELECT * FROM oln, opt WHERE opt_cod = oln_opt_cod AND oln_cod IN ( '01Y0BIAN'',''05C2LARG'',''0661NO00') order by oln_cod ASC
The problem is in the IN condition and I don't know Why it added another '.
I tried also this method but I don't know how to bind parameters in this way:
$query = (new \yii\db\Query())
->select('*')
->from('oln, opt')
->where('opt_cod = oln_opt_cod')
->andwhere('in', 'oln_cod',[':oln_cod' => $var_query])
->addParams([':oln_cod' => $var_query])
->orderBy('oln_cod ASC')
->all();
Another ' is added because of escaping. Since $var_query is actually a string, it will be treated as single string value and any ' will be escaped to prevent SQL injection. You're building your IN condition in wrong way, you should bind every ID in IN separately:
$tupla = Yii::$app->db->createCommand(
"SELECT * FROM oln, opt WHERE opt_cod = oln_opt_cod"
. " AND oln_cod IN (:var_query1, :var_query2, :var_query3) order by oln_cod ASC"
)
->bindValue(':var_query1', 12345)
->bindValue(':var_query2', 6789)
->bindValue(':var_query3', 101258);
It probably will be easier to use foreach to bind all params. It is also much simpler with Yii wrapper, which has nice shortcut for building IN conditions:
$query = (new \yii\db\Query())
->select('*')
->from('oln, opt')
->where('opt_cod = oln_opt_cod')
->andwhere(['in', 'oln_cod', $split_var]) // $split_var is array of values
->orderBy('oln_cod ASC')
->all();
This is my sql.. When i run it to phpmyadmin it is run ok. But when i am going to run as DB:raw in laravel5.5 it shows error. Here, Auckland is not column name.
$result = DB::select("select DISTINCT(SELECT count(id) FROM
commercial_lease where LENGTH(CONCAT(region,city,"Auckland")) =
LENGTH(location) ) as listing_without_address ,(SELECT count(id) FROM
commercial_lease where LENGTH(CONCAT(region,city,"Auckland")) <
LENGTH(location)) as listing_with_address ,(SELECT count(id) FROM
commercial_lease WHERE first_agent_name = 'None' and
second_agent_name='None') as private_listing from commercial_lease");
You are mixing quotes. Query is covered by double quotes and for Auckland you are trying to put these in double quotes again which is issuing an error.
To fix this issue you can escape your string like \"Auckland\" or using single quotes 'Auckland'
$result = DB::select("select DISTINCT
(SELECT count(id) FROM commercial_lease where LENGTH(CONCAT(region,city,'Auckland')) = LENGTH(location) ) as listing_without_address ,
(SELECT count(id) FROM commercial_lease where LENGTH(CONCAT(region,city,\"Auckland\")) < LENGTH(location)) as listing_with_address ,
(SELECT count(id) FROM commercial_lease WHERE first_agent_name = 'None' and second_agent_name='None') as private_listing from commercial_lease");
I have the following query, which doesn't work:
$sql = "SELECT dma, COUNT(*) as dma_count, round(dma_count/32434 * 100) as dma_percent FROM {$table} where dma != '0' GROUP BY dma ORDER BY dma_count DESC;";
The reason (I know) it doesn't work is because I'm using dma_count in this part round(dma_count/32434 * 100).
What's the correct way to do this?
EDIT:
Additional challenge. Instead of using 32434, I want to use a variable. I get the variable like this:
$get_total = "SELECT count(DISTINCT `exuid`) from {$table};";
$total = $dbh->query($get_total)->fetchAll(PDO::FETCH_ASSOC);
so my query becomes (with the fix recommended in the comments)
$sql = "SELECT dma, COUNT(*) as dma_count, round(COUNT(*)/{$total} * 100) as dma_percent FROM {$table} where dma != '0' GROUP BY dma ORDER BY dma_count DESC;";
This doesn't work because I think $total is in the wrong format. How can I fix this?
EDIT AGAIN:
Got it! $total is just the count of my rows, so I have this instead.
SELECT dma, COUNT(*) as dma_count, round(COUNT(*)/(SELECT COUNT(*) FROM {$table}) * 100,2) as dma_percent FROM {$table} where dma != '0' GROUP BY dma ORDER BY dma_count DESC;"
you can use COUNT(*) in the equation instead of the alias, or the finial answer a sub query. In general avoid sub queries if you can use a join.
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.
I have the following code:
try
{
$sql = 'SELECT id, type, date, amount, description, category
FROM `transactions`
WHERE type = "income"
AND month(date) = '$monthselect'
ORDER BY `transactions`.`id` DESC
LIMIT 0,50';
$result2 = $pdo->query($sql);
}
Now, I want to give this month(Date) a variable which month I want to select. if I put 1, it will give me January. So i thought, if I define a variable with 1, I can use it to select a month, right?
$monthselect = 1;
It doesnt work. What am I doing wrong?
Use prepared statements:
$stm = $pdo->prepare('SELECT id, type, date, amount, description, category
FROM `transactions`
WHERE type = "income"
AND month(date) = ?
ORDER BY `transactions`.`id` DESC
LIMIT 0,50');
$stm->execute(compact('monthselect'));
$result2 = $stm->fetchAll();
Since you're not adding "1" directly in your query, I'm assuming here that the variable comes from user input.
To concatenate strings in PHP you need to use the . operator.
$sql = 'SELECT id, type, date, amount, description, category
FROM `transactions`
WHERE type = "income"
AND month(date) = ' . $monthselect . '
ORDER BY `transactions`.`id` DESC
LIMIT 0,50';
I'll frequently use double quotes to substitute variables in PHP:
$sql = "SELECT id, type, date, amount, description, category
FROM `transactions`
WHERE type = 'income'
AND month(date) = $monthselect
ORDER BY `transactions`.`id` DESC
LIMIT 0,50";
Note that you need to swap the existing double quotes (inside the string) to single quotes. You can escape them too, but I find this way makes it much more readable.
Your issue is that you are trying to use a variable inside single quotes, inside which php is not translated
I find by using double quote marks around my queries it allows me to not only use variables in them but to also be able to use single quote mark around the values passed to the db
$sql = "SELECT id, type, date, amount, description, category
FROM `transactions`
WHERE type = 'income'
AND month(date) = $monthselect
ORDER BY `transactions`.`id` DESC
LIMIT 0,50";