How can I rewrite this SQL into CodeIgniter's Active Records? - sql

SELECT *, SUM(tbl.relevance) AS relevance FROM
(
(
SELECT q_id,
MATCH(a_content) AGAINST ('бутон') AS relevance
FROM answers
WHERE
MATCH(a_content) AGAINST ('бутон')
)
UNION
(
SELECT q_id,
(MATCH(q_content) AGAINST ('бутон')) * 1.5 AS relevance
FROM questions
WHERE
MATCH(q_content) AGAINST ('бутон')
)
) AS tbl
JOIN questions ON questions.q_id = tbl.q_id
GROUP BY tbl.q_id
ORDER BY relevance DESC

Codeigniter currently does not have support for subqueries in its Active Records class.
You'll simply have to use this:
$this->db->query($your_query, FALSE);
Remember to pass that second argument, so that Codeigniter doesn't try to escape your query.

Well there is indeed a simple hack for subqueries in codeigniter. You have to do the following
Go to system/database/DB_active_rec.php
There if you are using version 2.0 or greater change this
public function _compile_select($select_override = FALSE)
public function _reset_select()
Remove public keyword and you will be able to use subqueries
And now
$data = array(
"q_id",
"MATCH(a_content) AGAINST ('?????') AS relevance"
);
$this->db->select($data);
$this->db->from("answers");
$this->db->where("MATCH(a_content) AGAINST ('?????')");
$subQuery1 = $this->db->_compile_select();
// Reset active record
$this->db->_reset_select();
unset($data);
$data = array(
"q_id",
"(MATCH(q_content) AGAINST ('?????')) * 1.5 AS relevance"
);
$this->db->select($data);
$this->db->from("questions");
$this->db->where("MATCH(q_content) AGAINST ('?????')");
$subQuery2 = $this->db->_compile_select();
// Reset active record
$this->db->_reset_select();
unset($data);
$data = array(
"q_id",
"SUM(tbl.relevance) AS relevance"
);
$this->db->select($data);
$this->db->from("$subQuery1 UNION $subQuery2");
$this->db->join("questions","questions.q_id = tbl.q_id");
$this->db->group_by("tbl.q_id");
$this->db->order_by("relevance","desc");
$query = $this->db->get();

Related

Can Laravel automatically switch between column = ? and column IS NULL depending on value?

When building a complex SQL query for Laravel, using ? as placeholders for parameters is great. However when the value is null, the SQL syntax needs to be changed from = ? to IS NULL. Plus, since the number of parameters is one less, I need to pass a different array.
To get it to work, I have written it like this, but there must be a better way:
if ($cohortId === null) {
// sql should be: column IS NULL
$sqlCohortString = "IS NULL";
$params = [
Carbon::today()->subDays(90),
// no cohort id here
];
} else {
// sql should be: column = ?
$sqlCohortString = "= ?";
$params = [
Carbon::today()->subDays(90),
$cohortId
];
}
$query = "SELECT items.`name`,
snapshots.`value`,
snapshots.`taken_at`,
FROM snapshots
INNER JOIN (
SELECT MAX(id) AS id, item_id
FROM snapshots
WHERE `taken_at` > ?
AND snapshots.`cohort_id` $sqlCohortString
GROUP BY item_id
) latest
ON latest.`id` = snapshots.`id`
INNER JOIN items
ON items.`id` = snapshots.`item_id`
ORDER by media_items.`slug` ASC
";
$chartData = DB::select($query, $params);
My question is: does Laravel have a way to detect null values and replace ? more intelligently?
PS: The SQL is for a chart, so I need the single highest snapshot value for each item.
You can use ->when to create a conditional where clause:
$data = DB::table('table')
->when($cohortId === null, function ($query) {
return $query->whereNull('cohort_id');
}, function ($query) use ($cohortId) {
// the "use" keyword provides access to "outer" variables
return $query->where('cohort_id', '=', $cohortId);
})
->where('taken_at', '>', $someDate)
->toSql();

SQL query to Laravel

I am trying to convert the following query to Laravel:
select libéllé
from application
where libéllé not in (select application_id from application_user
where user_id = $id)
Laravel whereNotIn supports closures for subqueries, so it will be as simple as this:
Using Eloquent:
// Add this to top of your file.
use App\{ Application, ApplicationUser };
// Get your entries.
$rows = Application::whereNotIn('libéllè', function($query) use ($id) {
$query->select('application_id')->from((new ApplicationUser)->getTable())->where('user_id', $id);
})->get(['libéllè']);
Using Query Builder:
$rows = DB::table('application')->whereNotIn('libéllè', function($query) use ($id) {
$query->select('application_id')->from('application_user')->where('user_id', $id);
})->get(['libéllè']);
Please Try it.
$results = DB::select(
select libéllé
from application
where (libéllé)
not in(
select application_id from application_user
where user_id = $id
)
);
Also see this answer: How to convert mysql to laravel query builder
Also see this documentation: https://laracasts.com/discuss/channels/laravel/laravel5-resolve-username-from-2-tables?page=1

Yii left join query

I want to execute the below sql query using Yii framework and need help on this.
SQL query
SELECT t.*, LP.name AS lp_name FROM `user` AS `t` LEFT JOIN `level_profiles` AS `LP` ON t.prof_i = LP.id WHERE t.bld_i IN (17)
So, i tried the below steps.
$usql = 't.bld_i IN (17)';
$criteria1 = new CDbCriteria;
$criteria1->select = 't.*, LP.*';
$criteria1->join = ' LEFT JOIN `level_profiles` AS `LP` ON t.prof_i = LP.id';
$criteria1->addCondition($usql);
$criteria1->order = 't.prof_i';
$result = User::model()->findAll($criteria1);
The above step is not allowing me to access the value from 'level_profiles' table.
Then, i tried to execute:
$usql = 't.bld_i IN (17)';
$result = User::model()->with('level_profiles', array(
'level_profiles'=>array(
'select'=>'name',
'joinType'=>'LEFT JOIN',
'condition'=>'level_profiles.id="prof_i"',
),
))->findAll($usql);
This is returning an error 'Relation "level_profiles" is not defined in active record class "User". '
I know this could be executed using the below method.
Yii::app()->db->createCommand('SELECT query')->queryAll();
But i dont want to use the above.
I am a beginner with Yii and tried to look into the forums. But, i am getting confused how to execute the query using "User::model()" approach .
class User extends CActiveRecord
{
......
public function relations()
{
return array(
'level_porfile_relation'=>array(self::BELONGS_TO, 'Level_Profiles_Modelname', 'prof_i'),
);
}
and your query will be:
$result = User::model()->with('level_porfile_relation')->findAll($usql);

codeigniter change complex query into active record

I have a codeigniter app.
My active record syntax works perfectly and is:
function get_as_09($q){
$this->db->select('m3');
$this->db->where('ProductCode', $q);
$query = $this->db->get('ProductList');
if($query->num_rows > 0){
foreach ($query->result_array() as $row){
$row_set[] = htmlentities(stripslashes($row['m3'])); //build an array
}
return $row_set;
}
}
This is effectively
select 'm3' from 'ProductList' where ProductCode='$1'
What I need to do is convert the below query into an active record type query and return it to the controller as per above active record syntax:
select length from
(SELECT
[Length]
,CONCAT(([width]*1000),([thickness]*1000),REPLACE([ProductCode],concat(([width]*1000),([thickness]*1000),REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','')),'')) as options
FROM [dbo].[dbo].[ProductList]) as p
where options='25100cr' order by length
I picture something like below but this does not work.
$this->db->select(length);
$this->db->from(SELECT [Length],CONCAT(([width]*1000),([thickness]*1000),REPLACE[ProductCode],concat(([width]*1000),([thickness]*1000),REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','')),'')) as options
FROM [dbo].[dbo].[ProductList]);
$this->db->where(options, $q);
$this->db->order(length, desc);
Help appreciated as always. Thanks again.
You can use sub query way of codeigniter to do this for this purpose you will have to hack codeigniter. like this
Go to system/database/DB_active_rec.php Remove public or protected keyword from these functions
public function _compile_select($select_override = FALSE)
public function _reset_select()
Now subquery writing in available And now here is your query with active record
$select = array(
'Length'
'CONCAT(([width]*1000)',
'thickness * 1000',
'REPLACE(ProductCode, concat((width*1000),(thickness*1000),REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','')),'')) as options'
);
$this->db->select($select);
$this->db->from('ProductList');
$Subquery = $this->db->_compile_select();
$this->db->_reset_select();
$this->db->select('length');
$this->db->from("($Subquery)");
$this->db->where('options','25100cr');
$this->db->order_by('length');
And the thing is done. Cheers!!!
Note : While using sub queries you must use
$this->db->from('myTable')
instead of
$this->db->get('myTable')
which runs the query.
Source

Get latest comment records and the corresponding post slugs in Wordpress

I have the following query for getting the latest comments:
global $wpdb;
$sql = "SELECT DISTINCT ID, post_title, post_password, comment_ID, comment_post_ID, comment_author, comment_date_gmt, comment_approved, comment_type,comment_author_url, SUBSTRING(comment_content,1,30) AS com_excerpt FROM $wpdb->comments LEFT OUTER JOIN $wpdb->posts ON ($wpdb->comments.comment_post_ID = $wpdb->posts.ID) WHERE comment_approved = '1' AND comment_type = '' AND post_password = '' ORDER BY comment_date_gmt DESC LIMIT 10";
$comments = $wpdb->get_results($sql);
I also want to get the name(slug) of the post for each comment, without running a query for each comment. Can you suggest a modification to the above query to achieve this? Better yet, can I do this using built-in Wordpress functions?
Basically I need:
$comments = array ( 'comment_object' => ... , 'post_name' => ... )
From my own Recent Comments code with minor edits:
/**
* #return object
*/
function recent_comments_query($limit)
{
global $wpdb;
$sql = "SELECT DISTINCT ID,
post_title,
post_name, // <- post name
post_password,
comment_ID,
comment_post_ID,
comment_author AS author,
comment_date_gmt,
comment_approved,
comment_type,
comment_author_url AS url,
SUBSTRING(comment_content, 1, 200)
AS comment_content
FROM $wpdb->comments
LEFT OUTER JOIN $wpdb->posts
ON (
$wpdb->comments.comment_post_ID = $wpdb->posts.ID
)
WHERE comment_approved = '1'
AND comment_type = ''
AND post_password = ''
ORDER BY comment_date_gmt DESC
LIMIT $limit";
return $wpdb->get_results($sql);
}
You’ll get back an object with $limit results or NULL.