Use PDO's bind param multiple times as variable - mysql

I was searching over the internet and i didnt find any solution.
Lets say i want to use one paramerer in PDO multiple times.
SELECT *
FROM `users`
INNER JOIN `user_names` ON `users`.`id`=`user_names`.`id`
WHERE `user_names`.`name` LIKE CONCAT('%', ? ,'%') OR `users`.`name` LIKE CONCAT('%', ? ,'%')
How can i avoid to use ? two times ? I am looking for something like this:
SELECT ? AS `search_name`, *
FROM `users`
INNER JOIN `user_names` ON `users`.`id`=`user_names`.`id`
WHERE `user_names`.`name` LIKE CONCAT('%', `search_name` ,'%') OR `users`.`name` LIKE CONCAT('%', `search_name` ,'%')
Thank you

You can join an extra subselect that contains the parameter value or (like I do below) the complete search string.
SELECT *
FROM `users`
INNER JOIN `user_names` ON `users`.`id`=`user_names`.`id`
CROSS JOIN (SELECT CONCAT('%', x.name, '%') as SearchString) x
WHERE `user_names`.`name` LIKE x.SearchString OR `users`.`name` LIKE x.SearchString

You cannot do this in the normal mode. The only way to get around this is to use named parameters with emulation mode turned on (PDO::ATTR_EMULATE_PREPARES).
I, however, typically advise against doing this though and just recommend using multiple bindParam statements using named parameters instead of question marks. So you can use :searchname1 and :searchname2 both connected with the same POST/GET variable.

Related

Mysql Join two tables on Like with Concat

I want to join two tables on a like clause. My schema is as the link:
Sql Fiddle 1
As you can see the result is empty.
But if I use like as follows:
Sql Fiddle 2
As you see I can get the results with name or des contains 'GRE'. So what's the problem here?
I searched the answer for a while, and found the suggested way to do this is the same as I did:
similar question
Any suggestions will be highly appreciated.
You are doing it correctly. you just have to use TRIM() to remove trailing whitespaces. Use it like
SELECT
a.id as app_id,a.app_name,a.des,
b.id as tag_id, b.name as tag_name
FROM aa_t_aaaa_app a
JOIN aa_t_aaaa_tag b
ON ((a.app_name LIKE CONCAT('%', TRIM(b.name) ,'%')) or (a.des Like CONCAT('%', TRIM(b.name) ,'%')))
order by a.id`

MySQL joins where one field has surrounding tags to be stripped

I have two MySQL tables, articoli and tabtranslations, and the join between them should be trivial
SELECT CodArt, Translation FROM articoli LEFT JOIN tabtranslations ON articoli.CodArt = tabtranslations.Chiave
BUT, while articoli.CodArt ha simple strings (A001, BS15, etc..), field tabtranslations.Chiave is filled with surronding tags like <CODART>A001</CODART>, <CODART>BS15</CODART> thus overcomplicating joins - and I cannot modify it...
Well, is there a way I can solve this problem? Thanks
A quick and dirty soulution would be like this:
SELECT CodArt, Translation
FROM
articoli LEFT JOIN tabtranslations
ON CONCAT('<CODART>', articoli.CodArt, '</CODART>') = tabtranslations.Chiave
I don't know, but maybe this will work?
SELECT CodArt, Translation
FROM articoli
LEFT JOIN tabtranslations ON tabtranslations.Chiave LIKE '%' + articoli.CodArt + '%'
Just in case 'CODART' isn't the only possible tag, you may want to use REGEXP in the join predicate, like so:
select *
from codart c
left join tabtranslations t
on t.chiave REGEXP CONCAT('<.*>', c.codart, '</.*>');
Here is a sample fiddle for you to try it out: http://sqlfiddle.com/#!9/d6c04/1

mysql JOIN Inside a JOIN and search a group_concatenated values

I cant seem to find a solution for Searching a group_concatenated value,
I have 3 table that are connected with id's
1st table have the same value with 2nd table, but no same value with 3rd,
2nd table have the same value with 1st and 3rd table,
I want to get the value inside 3rd table,
concat the values in accordance to Distinct ID's of 2nd table, display them, and be able to search
this are my tables look like
how do i search for the concatenated values
please if there's a better way, your help is much appreciated?
the query below is what i have so far
$query = $db->prepare("
SELECT
a.problem_encountered,
GROUP_CONCAT(
DISTINCT
c.full_name)
AS
fnames
FROM
maintenance_sheet_table a
LEFT JOIN
mis_incharge_table b
ON
b.mis_incharge_id = a.mis_incharge_id
INNER JOIN
users_table c
ON
c.mis_id=b.mis_id
WHERE
a.problem_encountered
LIKE
:findMe
HAVING
fnames
LIKE
:findMe
GROUP BY a.id ORDER BY a.id
");
$query->bindValue(':findMe', '%' . $keywordSearch. '%');
A potential answer is to filter the Users_table in a subquery. There are a number of different forms of this option, and hard to tell from your data which is required. The one I have below simply returns the users that match the search criteria.
SELECT a.problem_encountered, GROUP_CONCAT(DISTINCT innerc.full_name) AS fnames
FROM maintenance_sheet_table a
LEFT JOIN mis_incharge_table b ON b.mis_incharge_id = a.mis_incharge_id
LEFT JOIN (SELECT c.mis_id, c.full_name
FROM users_table c
WHERE c.full_name LIKE :findMe) innerc ON innerc.mis_id=b.mis_id
WHERE a.problem_encountered LIKE :findMe
GROUP BY a.id
ORDER BY a.id
However, you could also do the concatenation within the subquery if required.
SELECT a.problem_encountered, innerc.fnames
FROM maintenance_sheet_table a
INNER JOIN (SELECT mit.mis_incharge_id, GROUP_CONCAT(DISTINCT ut.full_name) AS fnames
FROM users_table ut
INNER JOIN mis_incharge_table mit ON ut.user_id = mit.user_id
GROUP BY mit.mis_incharge_id
HAVING fnames LIKE :findMe) innerc ON innerc.mis_incharge_id = a.mis_incharge_id
WHERE a.problem_encountered LIKE :findMe
GROUP BY a.id
ORDER BY a.id
Note: I agree with spencer7593, that you shouldn't use the same :findMe variable against 2 separate fields. Even if it works, to a maintenance programmer or even yourself in a few years time, will probably look at this and think that the wrong fields are being interrogated.
You can "search" the return from the GROUP_CONCAT() expression in the HAVING clause. As a more efficient alternative, I suspect you could use an EXISTS predicate with a subquery.
I suspect part of the problem is that your query is referencing the same bind placeholder more than one time. (In previous releases of PDO, this was a restriction, a named bind placeholder could be referenced only once.)
The workaround to this issue is to use a separate bind placeholder, e.g.
HAVING fnames LIKE :findMeToo
And then bind a value to each placeholder:
$query->bindValue(':findMe', '%' . $keywordSearch. '%');
$query->bindValue(':findMeToo', '%' . $keywordSearch. '%');
(With this issue, I don't think PDO issued a warning or error; the effect was as if no value was supplied for the second reference to the named bind placeholder. Not sure if this issue is fixed, either by a code change or a documentation update. The workaround as above, reference a bind placeholder only once within a query.)
Beyond that, it's not clear what problem you are observing.
Your HAVING clause should come after your GROUP BY clause
change
HAVING
fnames
LIKE
:findMe
GROUP BY a.id ORDER BY a.id
to
GROUP BY a.id
HAVING
fnames
LIKE
:findMe
ORDER BY a.id

Correct syntax of using MySQL LIKE?

I have query with a bunch of LIKE statenements. I want to optizimze/explain the query, which runs fine. However if I copy this:
SELECT a.*, p.ek, p.vk, p.waehrung, p.onlinepreis
FROM arts a USE INDEX (i_aktiv, i_iln, i_marke )
LEFT JOIN pls p ON
p.iln = a.iln
LEFT JOIN fbs zu
ON a.farbe = zu.farbe
WHERE a.aktiv = "ja"
AND (
a.artikelbezeichnung LIKE ?
OR a.artikelbezeichnung_lang LIKE ?
OR ( a.farbe LIKE '%decke%'
OR zu.systemfarbe LIKE '%decke%'
OR zu.systemfarbe_en LIKE '%decke%'
)
)
)
...
As parameters I want to add '%decke%' but MySQL keeps throwing an error, if I use the %%.
Any idea what I'm doing wrong?
The error I'm getting is:
you have an error in your SQL-syntax.... check near... %'%'decke%' at OR ( a.farbe LIKE '%decke%' ...
For wildcarded LIKE comparisons, you have to fake it:
WHERE somefield LIKE CONCAT('%', ?, '%')
wildcarded 'likes' are one place that parameterized queries fall flat on their faces.

Comparing two tables with a LIKE and CONCAT %

I have two tables
USERS Contains user data
Mobilephone
447777744444
447777755555
7777755555
7777766666
MOBILEPHONES Contains mobile phone numbers
Telephone No
7777744444
7777733333
7777755555
7777766666
If I run the follow SQL it returns ONLY numbers that match exactly and does not perform the wildcard search.
SELECT MobilePhones.*, users.FirstName FROM MobilePhones
LEFT JOIN users
ON (users.MobilePhone= MobilePhones.`Telephone No`)
WHERE users.MobilePhone LIKE CONCAT('%', MobilePhones.`Telephone No`, '%')
I get returned
7777755555
7777766666
What I want is
7777755555
7777766666
447777755555
447777744444
I think you probably want to move your WHERE clause into the ON clause of the join, replacing the existing ON clause, which is doing the exact match:
SELECT MobilePhones.*, users.FirstName
FROM MobilePhones
LEFT JOIN users ON users.MobilePhone LIKE CONCAT('%', MobilePhones.`Telephone No`, '%')