mySQL query - Use results again in same query - mysql

I actually don't have any code yet to provide..but I can give you the data I am trying to manipulate.
I am working with a set of tags/keywords. Keywords can be related to another via the 'related_id' column.
So my table looks like:
keyword_tbl:
keyword_id | keyword | related_id
For this example, lets imagine the table is populated with the following entries
Entry 1:
keyword_id : 1
keyword: Marathons
related_id: 0
Entry 2:
keyword_id : 2
keyword: Boston
related_id: 1
As you can see, this entry of Boston, is related to Marathons via the related_id
I am working on giving the user the ability to search. If they search for an individual term, thats easy and not the question. However, if they search for "Boston Marathon," I now am having difficulty with the query.
SELECT * FROM keyword WHERE keyword LIKE "%boston%" OR keyword LIKE "%marathon%"
After this initial query, i'd like to compare the results, which would be the 2 entries I detailed above.
Id like to return only the term that is related to the other. In this case, Boston is the 'lowest' common denominator, and thus, I'd like to return it.
Imagine: Marathons -> Boston
Can this be done in a single query?
Thanks!

I'm thinking something like this might do the trick:
SELECT
a.*
FROM keyword a
JOIN keyword b
ON (a.related_id = b.keyword_id)
WHERE (a.keyword LIKE "%boston%"
OR a.keyword LIKE "%marathon%")
AND (b.keyword LIKE "%boston%"
OR b.keyword LIKE "%marathon%")

The below query will give you the answer
Marathons -> Boston.
IF there is a keyword that does not have a relation it will be displayed as
IceCream ->
SELECT resultset1.keyword,'->',IF(resultset2.keyword IS NOT NULL,resultset2.keyword,'')
FROM
(SELECT * FROM keyword WHERE keyword LIKE "%boston%" OR keyword LIKE "%marathon%")
as resultset1
LEFT JOIN
(SELECT * FROM keyword WHERE keyword LIKE "%boston%" OR keyword LIKE "%marathon%")
as resultset2
on resultset1.keyword_id=resultset2.related_id;

Related

Is it possible in MySQL to select strings that contains part that are referenced in another column?

Here is an example, my "reference" is as follow:
| Zeus
| Poseidon
| Apollon
Then I've got this "to compare" table:
Poseidon benediction
Random benediction
Power from Zeus
And what I want is some thing like this:
Poseidon benediction | Poseidon
Power from Zeus | Zeus
Is there a way to compare the content of the strings with the reference table ?
What I tried :
WHERE ... IN (SELECT reference FROM referencetable)
but this compare the whole string row so return nothing because it's not contained in the reference table
WHERE ... LIKE CONCAT("%", (SELECT reference FROM referencetable), "%")
but this trhow and error because it work only for one reference value (error says thar ther is more than one row)
Is there a way to merge this 2 ideas to achieve my goal ?
You can use join with like:
select t.*, c.*
from t1 join
tocompare c
on c.reference like concat('%', t1.col, '%');

mysql query to find all possible like combinations start with and ends with

In Mysql I have a table like this
And I want to filter only those records that can either start with or ends with all the below possible combinations in the groupname column. (sm.code)
196
328
2600
2708
3666
4453
4460
4468
4469
I tried a query but have some problem in finding all possible combinations.
SQL:-
select cr.groupname,cr.description,cr.higher_limit,cr.lower_limit, ce.severity from compatibility_rule as cr
join starting_material as sm on sm.id=cr.starting_material_id
join component as c on c.id=sm.component_id and c.cas_number in ('67-56-1','67-64-1')
join compatibility_error as ce on ce.id=cr.compatibility_error_id
and (cr.groupname like concat('%: ', sm.code) and cr.groupname like concat(sm.code, ' : %'))
and c.active=true and sm.active=true and cr.active=true
order by cr.groupname;
I might have to tweek something in this part, but not sure how.
and (cr.groupname like concat('%: ', sm.code) and cr.groupname like concat(sm.code, ' : %'))
Update:- Also posted simplified question in here
I have now created a sample on SQLFiddle below link
SQL Fiddel: http://sqlfiddle.com/#!9/54714e/39
I would like to filter only the group names that contains various combinations of values in the sm table. i.e. 100,101,2000.
The below query returns other combinations too like
100:2000
100:2001
101:2000
101:2001
SQL:-
select distinct d.groupname from docs d, sm s where d.groupname like concat(s.code,'%') or d.groupname like concat('%',s.code);
based on the schema that appears in http://sqlfiddle.com/#!9/54714e/1
you can use this query
select distinct * from (select d.id , d.groupname from docs as d,sm as s where d.groupname like (CONCAT("%",s.code)) or (CONCAT(s.code,"%"))) as t;

Trouble with MySQL query

OK, first-off I admit MySQL Syntax has never been my strongest point. So, here I am.
Urls :
ID Url Code
===============================================
1 http://www.google.com Abcd
2 http://www.freetemplates4u.com Efgh
3 ...
Posts :
ID Title Address
===============================================
1 Some Title 1 http://mize.it/Abcd
2 Some Title 2 http://mize.it/Efgh
3 ...
I want to create a query to fetch the following table
Title Url
=======================================================
Some Title 1 http://www.google.com
Some Title 2 http://www.freetemplates4u.com
In a few words :
Take the Url-Code pairs from Urls table
Search for http://mize.it/+Code in the Posts table (in the Address field)
Combine the final Title and Url in a result table.
I know it has something to do with joins and concatenation, but I'm definitely lost.
SIDENOTE : I don't care neither about my current database's structure, nor about performance issues. All I want is to transfer existing data, from the existing database (without having to alter it), to my new website's database (under a totally different format/structure).
You should change your DB-Design, this query will have a poor performance since mysql has to do a full tablescan.
Try adding a code column in your Posts table hat has the right value (populate it on insert/update) and add an index to Code (both tables).
Now you should be able to do.
SELECT Posts.Title, Urls.Url
FROM Posts
INNER JOIN Urls ON Post.Code = Urls.Code
Update:
If the first part of the url is always the same, this will work
SELECT Post.Title, Urls.Url
FROM Posts
INNER JOIN Urls ON Post.Adress = CONCAT('http://mize.it/', Urls.Code)
TRY
SELECT p.title,x.url
FROM Posts p
INNER JOIN ( SELECT url, CONCAT('http://mize.it/',code) AS xcode FROM Urls ) x
ON (x.xcode = p.address)
Working DEMO
This is a different approch, it took a while for me to test it.
Since your Address field contains complete url and we only need to match what is after / so we can replace actual url with nothing (I assume url is always the same) and have string ready to be matched with Code field.
SELECT b.Title, a.URL
FROM Url a
LEFT JOIN Posts b
ON a.Code = REPLACE(b.Address, 'http://mize.it/', '')
ORDER BY a.ID ASC
Check following query.
select m1.Url, m2.Title from Urls as m1, Posts as m2
where m2.address like 'http://mize.it/%'

Query Multiple Rows in the same Table for one Variable

I have a table setup like this:
session_id | event_id | moderator | speaker_1 | speaker_2 | speaker_3 | ...keeps going to speaker_10
What I am trying to do is setup a query that searches for 1 variable "speakerid = 13245" and check rows
'moderator', 'speaker_1', 'speaker_2', 'speaker_3', 'speaker_4', 'speaker_5', 'speaker_6', 'speaker_7', 'speaker_8', 'speaker_9', 'speaker_10'
Then return every 'session_id' corresponding to any row that contains speakerid = 12345 in any of the 11 speaker rows.
I know it has something to do with an INNER JOIN but after a lot of searching I can't find anything specific enough. I've been following stackoverflow for years now and this is my first ever post.
It really sounds like you need to normalize this table and have a table of sessions/events and a table of speakers related to it through a third sesssions_speaker table. That way you don't need to change your table schema when you have an event with 12+ speakers.
That being said, you can query like this to get the result you need
SELECT session_id
FROM table
WHERE
moderator = ?
OR speaker_1 = ?
OR speaker_2 = ?
...
OR speaker_11 = ?
I think you just need to use LIKE with OR to return the rows where any field contains "speakerid = 12345":
SELECT Session_Id
FROM YourTable
WHERE Moderator Like '%speakerid = 13245%'
OR speaker_1 Like '%speakerid = 13245%'
OR ...
You should read up on database normalization as speaker_n columns are a bad sign. You probably want a Speakers table amd a "Session-Speakers" mapping table. This would certainly make your query easier, but for now you have no choice but to search all columns:
SELECT sesion_id FROM t1 WHERE
moderator = '12345'
OR speaker_1 = 12345
etc.
You can do this using in in the where clause:
select session_id
from t
where 13245 in (moderator, speaker_1, speaker_2, speaker_3, speaker_4,
speaker_5, speaker_6, speaker_7, speaker_8, speaker_9,
speaker_10)

Is it possible to condense the result of multiple rows into a set object on one row in an SQL query?

I'm refactoring some code, and looking at ways to try and improve both readability and performance.
One item that bugs me is situations where I need a join statement with multiple objects on one side. For example...
Foo Schema Bar 2 Schema
-------------- ---------------
id id
data fooId
data
Result from Search:
---------------------
id barId fooData
1 1 ...
1 2 ...
1 3 ...
2 4 ...
3 5 ...
My end result, when querying for object Foo, needs to be an object Foo containing the id's (or objects fetched based on the id's) that are related.
Currently, I wind up having to condense multiple rows at the PHP level, adding bar id's to Foo until the foo id changes. It's a bit ugly, but it does work. What'd I'd like to reduce my result set to would be:
Result from Search:
---------------------
id barIds fooData
1 [1,2,3] ...
2 4 ...
3 5 ...
Is there any way to do this at the SQL level? (As a note, I'm not looking for the literal string 1, 2, 3, I want an array consisting of the id's 1, 2, and 3 -- but if I have to take a string and then transform, I can do)
As an aside, my intent is to combine this with the PDO::fetch_class to let me instantiate the class in a single line instead of spending time writing many lines of cookie-cutter code to load the properties of the class.
Sounds like you're looking into using GROUP_CONCAT. This will combine all the bar ids together. Something like this:
SELECT F.Id, GROUP_CONCAT(B.Id) BarIds, F.data
FROM Foo F
INNER JOIN Bar B ON F.Id = B.FooId
GROUP BY F.Id
If you'd like to get your exact format, try using CONCAT:
CONCAT('[',GROUP_CONCAT(B.Id),']') BarIds
Here's a SQL Fiddle Demo.
--EDIT--
If there is a concern over the length of characters stored by default with GROUP_CONCAT (check this link out), another alternative approach would be to mimic the behavior of GROUP_CONCAT by doing something like this:
SELECT Id, BarIds, Data
FROM (
SELECT F.Id,
MAX(#barIdsCombined:=IF(#prevFoodId=F.Id,
CONCAT(#barIdsCombined,',',B.Id),
B.Id)) BarIds,
F.data,
#prevFoodId:=F.Id
FROM Foo F
INNER JOIN Bar B ON F.Id = B.FooId
JOIN (SELECT #barIdsCombined:='') t
GROUP BY F.Id
) t