LIKE query not working as expected - sql

I have an SQL Query that looks like:
SELECT "medical_interventions"."id" AS t0_r0,
"medical_interventions"."refcode" AS t0_r1,
"medical_interventions"."intervention_tid" AS t0_r2,
"medical_interventions"."medical_intervention_category_id" AS t0_r3,
"medical_interventions"."created_at" AS t0_r4,
"medical_interventions"."updated_at" AS t0_r5, "translations"."id" AS
t1_r0, "translations"."lang" AS t1_r1, "translations"."text" AS t1_r2,
"translations"."created_at" AS t1_r3, "translations"."updated_at" AS
t1_r4 FROM "medical_interventions" LEFT OUTER JOIN "translations" ON
"translations"."id" = "medical_interventions"."intervention_tid" AND
"translations"."lang" = 'fr' WHERE (medical_intervention_category_id
=7 AND text like '%é%')
I have a text in there labeled évaluer
When I search fore just é as in the query above, I get évaluer as I expect. However, if I try év:
SELECT "medical_interventions"."id" AS t0_r0,
"medical_interventions"."refcode" AS t0_r1,
"medical_interventions"."intervention_tid" AS t0_r2,
"medical_interventions"."medical_intervention_category_id" AS t0_r3,
"medical_interventions"."created_at" AS t0_r4,
"medical_interventions"."updated_at" AS t0_r5, "translations"."id" AS
t1_r0, "translations"."lang" AS t1_r1, "translations"."text" AS t1_r2,
"translations"."created_at" AS t1_r3, "translations"."updated_at" AS
t1_r4 FROM "medical_interventions" LEFT OUTER JOIN "translations" ON
"translations"."id" = "medical_interventions"."intervention_tid" AND
"translations"."lang" = 'fr' WHERE (medical_intervention_category_id
=7 AND text like '%év%')
I get absolutely no results.
Is there something I do not understand about LIKE? Is there an alternate function I could use for searches?
AR:
def self.find_by_search_query_and_problem_id(search_query, problem_id)
problem = Problem.find(problem_id)
category = ProblemCategory.find(problem.category_id)
medIntCategory = MedicalInterventionCategory.find_by_category_text(category.category.text)
search = search_query
query = "medical_intervention_category_id =" + medIntCategory.id.to_s + " AND text like ?"
return self.includes(:intervention).where(query, "%#{search}%").references(:intervention)
end
In the controller
def search
#interventions = MedicalIntervention.find_by_search_query_and_problem_id(URI.unescape(params[:search_query]),params[:problem_id])
end
In JS:
getInterventionsFromSearch: function(search_query, problem_id)
{
var interventions = new MedicalIntervetionsCollection();
// fetch data on url AJAX
if(search_query != "")
{
interventions.url = "medical_interventions_search?search_query="+encodeURIComponent(search_query) +
"&problem_id=" + problem_id;
interventions.fetch();
}
return interventions;
}

See this post: How to SQL compare columns when one has accented chars?
Another idea:
There is an easy solution, but not very elegant.
Use the REPLACE function, to remove your accents. Exemple:
SELECT YOUR_COLUMN FROM YOUR_TABLE WHERE replace(replace(replace(replace(replace(replace(replace(replace(
replace(replace(replace( lower(YOUR_COLUMN), 'á','a'), 'ã','a'), 'â','a'), 'é','e'), 'ê','e'), 'í','i'),
'ó','o') ,'õ','o') ,'ô','o'),'ú','u'), 'ç','c') LIKE 'SEARCH_KEY%'
Where SEARCH_KEY is the key word that you wanna find on the column.
Or:
A possible solution would be a User-Defined-Function (UDF). There is a document here describing how to create such a function for SQLite in PHP. You could write a function called DROPACCENTS()

Related

Query with select and count in laravel

I did this Query in SQL but I can't make it work in Eloquent.
Please help me.
SELECT
tags.desc,
COUNT(planificacion_info.id_area) as cantidad_intervenciones
FROM
tags
INNER JOIN planificacion_info ON planificacion_info.id_area = tags.id_tag
WHERE
tags.grupo = 'area' and tags.estado = true
GROUP BY
tags.desc
You can do it like this :
$result = \DB::table('tags')->selectRaw('tags.desc, COUNT(planificacion_info.id_area) as cantidad_intervenciones')
->join('planificacion_info', 'planificacion_info.id_area', '=', 'tags.id_tag')
->where('tags.grupo', 'area')
->whereRaw('tags.estado = true')
->groupBy('tags.desc')
->get();
which gives you this request :
SELECT
tags.desc,
COUNT(planificacion_info.id_area) AS cantidad_intervenciones
FROM
`tags`
INNER JOIN `planificacion_info` ON `planificacion_info`.`id_area` = `tags`.`id_tag`
WHERE
`tags`.`grupo` = 'area'
AND tags.estado = TRUE
GROUP BY
`tags`.`desc`
Would be something liek this
$tags= DB::table('tags')
->select('tags.desc',DB::raw("COUNT(planificacion_info.id_area) AS cantidad_intervenciones")
->innerJoin('planificacion_info','planificacion_info.id_area','=','tags.id_tag')
->where('tags.grupo','area')
->where('tags.estado',true)
->groupBy('tags.desc')
->get();

Using the SELECT operator 'AND' only if a variable is set

What is the correct/efficient way to display results based on a variable if the variable is set? If variable is not set, the AND operator should not be used.
I apologize if this is a repeat, I clicked the suggested links and they did not make sense to me.
Near the end of code is my note with ^^^^^ marked.
For example:
$whatever = 123;
SELECT
DISTINCT terms.name as product_type_name,
tax.term_id as termidouter
FROM $wpdb->posts AS p
INNER JOIN wp_term_relationships r
ON p.ID = r.object_id
INNER JOIN wp_term_taxonomy tax
ON r.term_taxonomy_id = tax.term_taxonomy_id
INNER JOIN wp_terms terms
ON tax.term_id = terms.term_id
WHERE
tax.taxonomy = 'product_type'
AND p.post_status = 'publish'
AND p.post_type = 'product'
AND '$whatever ' = terms.term_id
^^^^ If $whatever is empty, I want to return results as if this line did not exist.
ORDER BY product_type_name
");
I was going to do an IF/ELSE but I figured that was the lazy way.
$whatever = 123;
if (empty($whatever)) {
// SELECT without the AND
} else {
// SELECT with the AND
}
You could do something like this:
AND CASE WHEN '$whatever ' IS NOT NULL THEN '$whatever ' ELSE terms.term_id END = terms.term_id
So... typically you'd want to use prepared statements, but if we're going this route, I would collect all my optional search criteria in an array as strings:
$myTerms=array();
if(!empty($whatever)) {
$myTerms[]="terms.term_id='" . $whatever . "'";
}
...
Then you can build your query easily like so:
$mySql = "SELECT * FROM whatever WHERE somefield='somevalue' ";
if(count($myTerms)>0) {
$mySql.=" AND " . implode(" AND ", $myTerms);
}
Please note that this is a basic example; you should also be checking any value you pass into your query for attacks etc.

Oracle error: Not a group by function

Select EVENTPLAN.PLANNO, EVENTPLANLINE.LINENO, RESOURCETBL.RESNAME,
COUNT(EVENTPLANLINE.NUMBERFLD) AS NUMBEROFRESOURCES,
LOCATION.LOCNAME, EVENTPLANLINE.TIMESTART, EVENTPLANLINE.TIMEEND
FROM EVENTPLAN, RESOURCETBL, EVENTPLANLINE, LOCATION, FACILITY
WHERE EVENTPLAN.PLANNO = EVENTPLANLINE.PLANNO
AND EVENTPLANLINE.RESNO = RESOURCETBL.RESNO
AND EVENTPLANLINE.LOCNO = LOCATION.LOCNO
AND FACILITY.FACNO = LOCATION.FACNO
AND FACILITY.FACNAME = 'Basketball arena'
AND EVENTPLAN.ACTIVITY = 'Operation'
AND EVENTPLAN.WORKDATE BETWEEN '1-OCT-13' AND '31-DEC-13'
GROUP BY EVENTPLAN.PLANNO, EVENTPLANLINE.LINENO,
RESOURCETBL.RESNAME,EVENTPLANLINE.NUMBERFLD;
On running this query I am getting an error: Not a group by function. Can someone please tell me why am I getting this error? I have added all the fields in the GROUP BY function.
When you use an aggregate function ALL scalar fields must be in GROUP BY function.
You have missed these:
LOCATION.LOCNAME, EVENTPLANLINE.TIMESTART, EVENTPLANLINE.TIMEEND
So, the right query will be:
SELECT
EVENTPLAN.PLANNO, EVENTPLANLINE.LINENO, RESOURCETBL.RESNAME,
COUNT(EVENTPLANLINE.NUMBERFLD) AS NUMBEROFRESOURCES,
LOCATION.LOCNAME, EVENTPLANLINE.TIMESTART, EVENTPLANLINE.TIMEEND
FROM EVENTPLAN, RESOURCETBL, EVENTPLANLINE, LOCATION, FACILITY
WHERE EVENTPLAN.PLANNO = EVENTPLANLINE.PLANNO
AND EVENTPLANLINE.RESNO = RESOURCETBL.RESNO
AND EVENTPLANLINE.LOCNO = LOCATION.LOCNO
AND FACILITY.FACNO = LOCATION.FACNO
AND FACILITY.FACNAME = 'Basketball arena'
AND EVENTPLAN.ACTIVITY = 'Operation'
AND EVENTPLAN.WORKDATE BETWEEN '1-OCT-13' AND '31-DEC-13'
GROUP BY EVENTPLAN.PLANNO, EVENTPLANLINE.LINENO, RESOURCETBL.RESNAME,
LOCATION.LOCNAME, EVENTPLANLINE.TIMESTART, EVENTPLANLINE.TIMEEND

ActiveRecord has_many with multiple conditions

I'm trying to find an object by checking for several of its relations.
Loan.joins(:credit_memo_attributes)
.where(credit_memo_attributes: {name: 'pr2_gtx1_y', value: '2014'})
.where(credit_memo_attributes: {name: 'pr1_gtx1_y', value: '2013'})
.where(credit_memo_attributes: {name: 'tx1_y', value: '2014'})
Calling to_sql on that gives:
"SELECT `loans`.* FROM `loans` INNER JOIN `credit_memo_attributes`
ON `credit_memo_attributes`.`loan_id` = `loans`.`id`
WHERE `credit_memo_attributes`.`name` = 'pr2_gtx1_y' AND `credit_memo_attributes`.`value` = '2014'
AND `credit_memo_attributes`.`name` = 'pr1_gtx1_y' AND `credit_memo_attributes`.`value` = '2013'
AND `credit_memo_attributes`.`name` = 'tx1_y' AND `credit_memo_attributes`.`value` = '2014'"
So, I'm checking for Loans that have credit_memo_attributes with all of those attributes. I know at least 1 of our 20,000 loans meets this criteria, but this query returns an empty set. If I only use 1 of the where clauses, it returns several, as I'd expect, but once I add even 1 more, it's empty.
Any idea where I'm going wrong?
Update:
Based on comments I believe you want multiple joins in your criteria. You can do that like this:
attr_1 = {name: 'pr2_gtx1_y', value: '2014'}
attr_2 = {name: 'pr1_gtx1_y', value: '2013'}
attr_3 = {name: 'tx1_y', value: '2014'}
Loan.something_cool(attr_1, attr_2, attr_3)
class Loan < ActiveRecord::Base
...
def self.something_cool(attr_1, attr_2, attr_3)
joins(sanitize_sql(["INNER JOIN credit_memo_attributes AS cma1 ON cma1.loan_id = loans.id AND cma1.name = :name AND cma1.value = :value", attr_1]))
.joins(sanitize_sql(["INNER JOIN credit_memo_attributes AS cma2 ON cma2.loan_id = loans.id AND cma2.name = :name AND cma2.value = :value", attr_2]))
.joins(sanitize_sql(["INNER JOIN credit_memo_attributes AS cma3 ON cma3.loan_id = loans.id AND cma3.name = :name AND cma3.value = :value", attr_3]))
end
If you look at the SQL generated (that you included in your question, thank you) you'll see that all those conditions are being ANDed together. There are NO rows for which name = 'pr2_gtx1_y' AND name = 'pr1_gtx1_y' (and so forth). So you are getting the result I would expect (no rows).
You can put all names and values into array like ids and years and pass those into where clause like this. Active Record will query all the values in the array.
Loan.joins(:credit_memo_attributes)
.where(credit_memo_attributes: {name: ids, value: years})
Personally I'm still learning active record, in this concern i don't think active record supports multiple where clauses.
Notice how the SQL version is returning your code: it is joining the requirements with an AND.
"SELECT `loans`.* FROM `loans` INNER JOIN `credit_memo_attributes`
ON `credit_memo_attributes`.`loan_id` = `loans`.`id`
WHERE `credit_memo_attributes`.`name` = 'pr2_gtx1_y' AND `credit_memo_attributes`.`value` = '2014'
AND `credit_memo_attributes`.`name` = 'pr1_gtx1_y' AND `credit_memo_attributes`.`value` = '2013'
AND `credit_memo_attributes`.`name` = 'tx1_y' AND `credit_memo_attributes`.`value` = '2014'"
Now, this is next to impossible. An Object.name can never be all pr2_gtx1_y, pr1_gtx1_y, and tx1_y. Same goes for the value attributes.
What you need here is an OR as opposed to the AND.
To this effect, try to change your query to the following:
Loan.joins(:credit_memo_attributes)
.where(
"credit_memo_attributes.name = ? and credit_memo_attributes.value = ?
OR credit_memo_attributes.names = ? and credit_memo_attributes.value = ?
OR credit_memo_attributes.name = ? and credit_memo_attributes.value = ?",
'pr2_gtx1_y', '2014',
'pr1_gtx1_y', '2013',
'tx1_y', '2014'
)

How to get particular column in zend using Left join

I am new to zend framework,
Following is the plain mysql query which takes particular column from table,
SELECT jobs_users.id,jobs_users.first_name from jobs_users left join friends on jobs_users.id=friends.friend_id where friends.member_id=29
I tried with zend to implement the above query like below,
public function getFriendsProfileList($id){
$db = Zend_Db_Table::getDefaultAdapter();
$select = $db->select();
$select->from('jobs_users')
->joinLeft(
'friends',
'jobs_users.id=friends.friend_id',
array('jobs_users.id','jobs_users.first_name','jobs_users.last_name','jobs_users.photo')
)
->where("friends.member_id = ?", $id);
$result = $db->fetchAll($select);
return $result;
}
Here i got result with all column name , not with exact column name which i have given in query.
Kindly help me on this.
Use this instead:
$select->from('jobs_users', array('jobs_users.id','jobs_users.first_name','jobs_users.last_name','jobs_users.photo'))
->joinLeft('friends', 'jobs_users.id=friends.friend_id')
->where("friends.member_id = ?", '20');
You may also try this:
$select = $db->select();
$select->setIntegrityCheck(false);
$select->joinLeft('jobs_users','',array('jobs_users.id','jobs_users.first_name','jobs_users.last_name','jobs_users.photo'));
$select->joinLeft('friends','jobs_users.id=friends.friend_id', array());
$select->where("friends.member_id = ?", $id);
$result = $db->fetchAll($select);
return $result;