How to search exact string using MySql Query which avoids extended values? - mysql

My Query looks like
$search_query = db_query("SELECT nd.nid, users.name, nd.type FROM node as nd
LEFT JOIN node_revisions as nd_rev ON nd_rev.nid = nd.nid AND nd_rev.vid = nd.vid
LEFT JOIN users ON nd.uid = users.uid
WHERE nd.status = 1 AND nd_rev.body LIKE LOWER('%node/100%')
AND nd.nid NOT IN(SELECT DISTINCT nid FROM term_node WHERE tid = 293)");
This query actually returns all the matches from node_revisions.body field, Which includes
node/1000, node/1001.... Etc.,
I want to get only the result of exact match where possible like
"node/100"
"node/100/"
"/node/100"
"/node/100/"
'node/100'
'node/100/'
'/node/100'
'/node/100/'
and not like
"node/1006"
"node/10064/"
"/node/1000"
"/node/10001/"
'node/10023'
'node/1005/'
'/node/1001'
'/node/10069/'
This above query returned me result which has string like below..
..a href="/node/1006"
How to avoid this kind of errors? Please help..

Try removing the % after 100 so the search won't consider any digit after 100, like this:
LOWER('%node/100')

Then consider the following Regular Expression
Example:
`nd_rev.body` REGEXP "^/?node/100/?$"

Oh ya... I got an resolution for this.. I redefined my query like below and it gives me result as expected..
$search_query = db_query("SELECT nd.nid, users.name, nd.type FROM node as nd
LEFT JOIN node_revisions as nd_rev ON nd_rev.nid = nd.nid AND nd_rev.vid = nd.vid
LEFT JOIN users ON nd.uid = users.uid
WHERE nd.status = 1 AND nd_rev.body RLIKE '[[:<:]]" . $search_string . "[[:>:]]'
AND nd.nid NOT IN(SELECT DISTINCT nid FROM term_node WHERE tid = 293)");
Look at
nd_rev.body RLIKE '[[:<:]]" . $search_string . "[[:>:]]'
This is what i expected

Related

Codeigniter INNER JOIN with multiple ON [duplicate]

I want to select data from my database table with join query, but my it doesn't work.
My query:
$this->db->select();
$this->db->from('we');
$this->db->join('schedule', 'schedule.itemid = we.cid');
$this->db->join('schedule', 'schedule.itemtype = 'testitem'');
$this->db->where('we.isActive','Y');
This line makes problem with schedule.itemtype = 'testitem':
$this->db->join('schedule', 'schedule.itemtype = 'testitem'');
How can I solve this?
You don't need to join same table twice.
But just to extend ON clause:
$this->db->select();
$this->db->from('we');
$this->db->join('schedule', 'schedule.itemid = we.cid AND schedule.itemtype = \'testitem\'');
$this->db->where('we.isActive','Y');
try
$this->db->select();
$this->db->from("we");
$this->db->join("schedule", "schedule.itemid = we.cid");
$this->db->where("schedule.itemtype","testitem");
$this->db->where("we.isActive","Y");
I believe there are two problems here. The first problem is that you are using one too many quotes in the second join line in your query:
You have: $this->db->join('schedule', 'schedule.itemtype='testitem''); < extra quote
It should be: $this->db->join('schedule', 'schedule.itemtype=testitem');
Second problem: your join doesnt make sense.
Your statement:
$this->db->select();
$this->db->from('we');
$this->db->join('schedule', 'schedule.itemid = we.cid');
$this->db->join('schedule', 'schedule.itemtype = testitem');
$this->db->where('we.isActive','Y');
Translates to:
SELECT * FROM we
JOIN schedule ON schedule.itemid = we.cid
JOIN schedule ON schedule.itemtype = testitem
WHERE we.isActive = Y
As you can see you are joining the same table twice on different lines, not only that but what table does "testitem" belong to? We are left to assume that you perhaps want the join where itemtype = testitem which will mean this:
SELECT * FROM we
JOIN schedule ON schedule.itemid = we.cid
WHERE schedule.itemtype = testitem
AND we.isActive = Y
Therefore your final Codeigniter query should be:
$this->db->select('*');
$this->db->from('we');
$this->db->join('schedule', 'schedule.itemid = we.cid');
$this->db->where('schedule.itemtype', 'testitem');
$this->db->where('we.isActive','Y');
This will work:
$this->db->join('schedule', 'schedule.itemid = we.cid');
$this->db->where('we.isActive','Y');
$this->db->where('schedule.itemtype', 'testitem');
$this->db->get('we');
$this->db->query('select we_tbl.c_name from we we_tbl,schedule sch_tbl where sch_tbl.itemid = we_tbl.cid AND we_tbl.idActive = '.$activeData);
Try this query according to your problem this could get the data you need.
I've tested on different database but i tried to perform what you're trying to get. https://www.w3schools.com/sql/trysql.asp?filename=trysql_op_in
select
pro_tbl.ProductName,
cat_tbl.CategoryName ,
sup_tbl.SupplierName
from
Products pro_tbl,
Suppliers sup_tbl,
Categories cat_tbl
where
pro_tbl.SupplierID = sup_tbl.SupplierID AND
pro_tbl.CategoryID = cat_tbl.CategoryID;
Two possible problems, depending on what your desired outcome is:
If you need to make two joins and are getting an error with the second join clause, try using double quotes to enclose the constant value on the condition or you'll get a parse error:
$this->db->join('schedule', 'schedule.itemtype = "testitem"');
If you need to join only once with multiple conditions, use parentheses:
$this->db->select('*');
$this->db->from('we');
$this->db->join('schedule', '(schedule.itemid = we.cid AND schedule.itemtype="testitem")');
$this->db->where('we.isActive','Y');
You query is equivalent to writing:
select * from we
inner join schedule on schedule.itemid = we.cid
inner join schedule on schedule.itemtype = "testitem"
where we.isActive = 'Y'
but what you seem to need is
select * from we
inner join schedule on (schedule.itemid = we.cid AND schedule.itemtype = "testitem")
where we.isActive = 'Y'
On your original query, you are doing two joins. In the latter, you'll do only one with multiple conditions.

Use select filed result on LEFTJOIN string

I'm trying to use id_program result from the availability table inside a string in LEFTJOIN, is it possible?
I tried using this {post.id_program} but its not working.
SELECT *
FROM availability post
LEFT JOIN postmeta meta5 ON meta5.post_id = post.id_post
AND meta5.meta_key = 'items_iti_port_{post.id_program}_nights_iti_port'
WHERE post.id_post=462
EDIT:
http://sqlfiddle.com/#!9/aeb4a7/3
I see two ways..
Using CONCAT():
meta5.meta_key = CONCAT('items_iti_port_', post.id_program, '_nights_iti_port')
With REPLACE():
meta5.meta_key = REPLACE('items_iti_port_%_nights_iti_port', '%', post.id_program)

How can I get the latest package for all packages in SQL?

I have two tables, packages (with id, name as attributes) and releases (with url, upload_time, downloaded_bytes as attributes). Every package can have arbitrary many releases. I want a list of all packages with their latest release.
Currently, I have the following working code:
sql = ("SELECT `packages`.`id`, `name` FROM `packages`")
cursor.execute(sql)
packages = cursor.fetchall()
for pkg in packages:
sql = ("SELECT `url` FROM `releases` "
"WHERE `package_id` = %s "
"AND `downloaded_bytes` = 0 "
"ORDER BY `upload_time` DESC LIMIT 1")
cursor.execute(sql, (pkg['id'], ))
url = cursor.fetchone()
if url is not None:
package_url = url['url']
package_analysis.main(pkg['name'], package_url)
logging.info("Package '%s' done.", pkg['name'])
However, I think this is an ugly solution as I execute a lot of queries where I should only execute one query.
Can I do this in one query? How would the query look like?
Please note: I only want one result for each package. That means, the package numpy should only give the result for url="https://pypi.python.org/packages/cp35/n/numpy/numpy-1.10.1-cp35-cp35m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl" (version 1.10.1) and not 99 results.
What I've tried
SELECT
`packages`.`id`,
`packages`.`name`,
`releases`.`url`,
`releases`.`upload_time`,
`releases`.`release_number`
FROM
`packages`
JOIN
`releases` ON `releases`.`package_id` = `packages`.`id`
GROUP BY
`packages`.`name`
ORDER BY
`releases`.`upload_time` DESC
But that gives a seemingly random value for upload_time (and also url).
You can try this query:
select p.id, p.name, r.url, r.upload_time, r.release_number from
(select p.id, max(r.release_number) release_number from packages p
join releases r on p.id = r.package_id
group by p.id) a
join packages p on p.id = a.id
join releases r on r.release_number = a.release_number
It assumes that release_number is sortable, if not possible you can use max upload time instead.
Based on this answer (thank you Emiswelt) for mentioning it:
SELECT
`packages`.`id`,
`packages`.`name`,
`o`.`url`,
`o`.`upload_time`,
`o`.`release_number`
FROM
`releases` o
LEFT JOIN
`releases` b ON `o`.`package_id` = `b`.`package_id`
AND `o`.`upload_time` < `b`.`upload_time`
JOIN
`packages` ON `packages`.`id` = o.package_id
WHERE
`b`.`upload_time` is NULL
AND `o`.`downloaded_bytes` = 0
ORDER BY
`packages`.`name`
LIMIT 10
The query finishes execution within a fraction of a second.

Excluding a value from the return result of MySQL

I'm facing a problem and I'm not finding the answer. I'm querying a MySql table during my java process and I would like to exclude some rows from the return of my query.
Here is the query:
SELECT
o.offer_id,
o.external_cat,
o.cat,
o.shop,
o.item_id,
oa.value
FROM
offer AS o,
offerattributes AS oa
WHERE
o.offer_id = oa.offer_id
AND (cat = 1200000 OR cat = 12050200
OR cat = 13020304
OR cat = 3041400
OR cat = 3041402)
AND (oa.attribute_id = 'status_live_unattached_pregen'
OR oa.attribute_id = 'status_live_attached_pregen'
OR oa.attribute_id = 'status_dead_offer_getter'
OR oa.attribute_id = 'most_recent_status')
AND (oa.value = 'OK'
OR oa.value='status_live_unattached_pregen'
OR oa.value='status_live_attached_pregen'
OR oa.value='status_dead_offer_getter')
The trick here is that I need the value to be 'OK' in order to continue my process but I don't need mysql to return it in its response, I only need the other values to be returned, for the moment its returning two rows by query, one with the 'OK' value and another with one of the other values.
I would like the return value to be like this:
'000005261383370', '10020578', '1200000', '562', '1000000_157795705', 'status_live_attached_pregen'
for my query, but it returns:
'000005261383370', '10020578', '1200000', '562', '1000000_157795705', 'OK'
'000005261383370', '10020578', '1200000', '562', '1000000_157795705', 'status_live_attached_pregen'
Some help would really be appreciated.
Thank you !
You can solve this with an INNER JOIN on the self I think:
SELECT o.offer_id
,o.external_cat
,o.cat
,o.shop
,o.item_id
,oa.value
FROM offer AS o
INNER JOIN offerattributes AS oa
ON o.offer_id = oa.offer_id
INNER JOIN offerattributes AS oaOK
ON oaOK.offer_id = oa.offer_id
AND oaOK.value = 'OK'
WHERE o.cat IN (1200000,12050200,13020304,3041400,3041402)
AND oa.attribute_id IN ('status_live_unattached_pregen','status_live_attached_pregen','status_dead_offer_getter','most_recent_status')
AND oa.value IN ('status_live_unattached_pregen','status_live_attached_pregen','status_dead_offer_getter');
By doing a self-JOIN with the restriction of value OK, it will limit the result set to offer_ids that have an OK response, but the WHERE clause will still retrieve the values you need. Based on your description, I think this is what you were looking for.
I also converted your implicit cross JOIN to an explicit INNER JOIN, as well as changed your ORs to IN, should be more performant this way.

Mysql 4 to 5 query conversion - join headaches

If anyone can help me rewrite my query to work in mysql 5 I would be very grateful. If anyone can provide links to solid, simple tutorials on how to rewrite old queries that would also be great.
My current (version 4) query looks like this:
SELECT
course.course_code,
course.course_title_sv AS course_title,
course.course_u_credits,
course.course_successive_level_scb_id,
s.successive_level_scb_order,
s.successive_level_scb_code,
LEFT (education_level.edu_level_name_sv, 1) AS course_edu_level, course.course_level,
GROUP_CONCAT(DISTINCT h.head_area_hv_title_sv SEPARATOR ', ') AS head_area_hv
FROM
course, course_event, course_event_package_links, package, education_level
LEFT JOIN
course_has_head_area_hv ON(course.course_id = course_has_head_area_hv.course_id)
LEFT JOIN
head_area_hv h ON(h.head_area_hv_id = course_has_head_area_hv.head_area_hv_id)
LEFT JOIN
successive_level_scb s ON(s.successive_level_scb_id = course.course_successive_level_scb_id)
WHERE
course.course_edu_level=education_level.edu_level_id AND
course.course_id=course_event.course_id AND
course_event.course_event_id=course_event_package_links.course_event_id AND
course_event_package_links.package_id=package.package_id AND
course.course_successive_level_scb_id != '' AND
package.package_id='6318'
GROUP BY course.course_id
Simply replace
SELECT ...
FROM course, course_event, course_event_package_links
...
WHERE course.course_id=course_event.course_id
AND course_event.course_event_id=course_event_package_links.course_event_id
by
SELECT ...
FROM course
JOIN course_event ON course_event.course_id = course.course_id
JOIN course_event_package_links
ON course_event_package_links.course_event_id = course_event.course_event_id
...
About your error message, are you sure course.course_id exists? Maybe it was replaced by course.course_code?