Joining 2 tables that use LIKE as a common identifier - mysql

I have two tables.
wp_rg_lead_detail:
id lead_id form_id field_number value
=====================================================
166649 2579 4 235 batman
167324 2602 4 235 batman
168439 2579 4 235 kelsey
169221 2836 4 235 batman
wp_rg_incomplete_submissions:
uuid form_id submission
=======================================================================
fds4389dsd2kjd 4 JSON entry that doesn't contain 'kelsey
ciwod2938slsck 4 JSON entry that contains 'kelsey
392copaa234jfl 4 JSON entry that doesn't contain 'kelsey
What I want to do is grab the record that:
has the word 'kelsey' in wp_rg_incomplete_submissions.submission
has a wp_rg_incomplete_submissions.form_id of 4
has the word 'kelsey' as a value in wp_rg_lead_detail
and the lead_id for that entry in wp_rg_lead_details should also have the word 'batman' for a value.
The only identifier between the two tables is the word 'kelsey'. But where it exists in wp_rg_lead_detail, that lead_id must also have an entry with the value of 'batman'.
I have tried subqueries and joins, and I'm getting nowhere. Can someone please point me in the right direction?
UPDATE
From the feedback below, it sounds like I should create an alias and then join them where that exists in both. Here's where I'm at:
SELECT *, 'kelsey' AS myvalue
FROM `wp_rg_lead_detail`
WHERE (`value` LIKE 'batman'
OR `value` LIKE 'kelsey')
AND `form_id` = 4
GROUP BY `lead_id`
HAVING count(*) > 1
I think somehow I need to join this where the LIKE uses myvalue:
SELECT *, uuid
FROM `wp_rg_incomplete_submissions`
WHERE `form_id` = 4
AND `submission` LIKE concat_ws(";", "%", myvalue, "%")
UPDATE #2
After continuing to struggle with this, I've come up with:
SELECT *
FROM wp_rg_lead_detail
INNER JOIN wp_rg_incomplete_submissions ON wp_rg_lead_detail.value
LIKE CONCAT('%', wp_rg_incomplete_submissions.submission, '%')
WHERE wp_rg_lead_detail.value = 'kelsey'
I know I'm doing something wrong because there are no results. But I feel it is much closer than where I started from.

So here is what I came up with, not vouching for it's efficiency as I don't write much SQL.
SELECT *
FROM submissions
JOIN (SELECT detail.*
FROM detail
JOIN detail detail2
ON detail2.lead_id = detail.lead_id
WHERE detail.value = 'kelsey'
AND detail2.value = 'batman'
) as detailjoin
ON detailjoin.form_id = submissions.form_id
WHERE submissions.submission LIKE '%kelsey%'
AND submissions.form_id = 4;
Which from you data set returns:
'ciwod2938slsck' 4 'JSON with kelsey' 168439 2579 4 235 'kelsey'
So to break it down, the inner join query gets all detail rows that have 'kelsey' as a value where that lead_id also exists in a row with a 'batman' value.
The outer query selects all rows with form_id of 4 and 'kelsey' in submission
Then it simply joins the two on form_id = form_id.
I believe this does what you needed although with the small data set not positive.

Related

Need help returning duplicates from a join onto a single line with a sum function included

I have two tables t1 and t2. t1 contains some message data i have set up to be searched against t2 which contains a list of keywords all with their own individual score. Now I have been moderately successful with this and have managed to return all rows in t1 that contain any keyword within t2 with this query
SELECT DISTINCT t1.RowID, t1.ChatNo, t1.UserNo,
t1.Chat, t2.Keywords, SUM(t2.KeywordScore) AS Score
FROM t1
LEFT JOIN t2 ON t1.Chat LIKE CONCAT('%', + t2.Keywords , + '%')
WHERE t2.Keywords IS NOT NULL OR t1.ChatNo > 0 AND t1.UserNo > 0
GROUP BY t1.RowID, t2.Keywords
Now my issue is, it returns duplicate results if a chat message has multiple keywords and on each duplicate row it will have picked up a different keyword and that keywords score. Now because of this I believe my query is attempting to sum the rows individually so cannot total them up (correct me if i am wrong).
for example:
RowID ChatNo UserNO Chat Keywords Score
1 1 1 "...ex1 ex2 ex3" ex1 2
1 1 1 "...ex1 ex2 ex3" ex2 4
1 1 1 "...ex1 ex2 ex3" ex3 1
Now what I would like it to do is to return all the keywords found in a message on a single line (or list) and still be able to SUM up the values of the keywords found within the message and display the total, like so:
RowID ChatNo UserNO Chat Keywords Score
1 1 1 "...ex1 ex2 ex3" ex1, ex2, ex3 7
I have done some searching and testing haven't really come across a solution that has worked for me. So if anyone can give me some assistance on how I might proceed and get the query to output the results on a single line with a the score summed up it would be greatly appreciated.
You need to use GROUP_CONCAT()
Also distinct doesn't seem necessary so I deleted it.
Try this:
SELECT t1.RowID, t1.ChatNo, t1.UserNo,
t1.Chat, group_concat(t2.Keywords, ', '), SUM(t2.KeywordScore) AS Score
FROM t1
LEFT JOIN t2 ON t1.Chat LIKE CONCAT('%', + t2.Keywords , + '%')
WHERE t2.Keywords IS NOT NULL OR t1.ChatNo > 0 AND t1.UserNo > 0
GROUP BY t1.RowID, t1.ChatNo, t1.UserNo, t1.Chat

MySQL query to gather incorrectly stored data

I have recently taken over a email campaign project and need to generate a report for the customer. However the data has been stored very strangely.
Basically the client wants a report of the subscribers first name and last name that have subscribed to a emailing list.
Example table data.
------------------------------------------------------------
id | owner_id | list_id | field_id | email_address | value
------------------------------------------------------------
1 10 1 137 me#example.com John
2 10 1 138 me#example.com Doe
So as you can see, John Doe has subscribed to mailing list 1, and field_id 137 is his first name and field_id 138 is his last name.
The client is looking for a export with the users first name and last name all is one field.
I tred the following sql query
SELECT value
FROM Table_A AS child
INNER JOIN Table_A AS parent
ON parent.email_address = child.email_address
WHERE child.owner_id = '10'
But unfortunately the query gives me the results in many rows but not appending the first name and last name into one field,
If anyone can provide some assistance that would be awesome.
Thanks.
SELECT
concat( parent.value,' ',child.value)name
FROM mytable AS child
left JOIN mytable AS parent
ON parent.email_address = child.email_address
WHERE child.owner_id = '10'
and parent.field_id=137 and child.field_id=138
Check at-http://sqlfiddle.com/#!9/199b4b/45
I think you have to use a variable to put in there everything you have to and then select the variable with the desired name of yours.
For example:
DECLARE #yourvariable VARCHAR(MAX)
SELECT #yourvariable = COALESCE(#yourvariable + " ") + value
FROM table_A
WHERE owner_id = 10
SELECT #yourvariable as FullName
Try that, it might help.
You can try this code(column name equals value in your original DB):
select a.name
from
table_a a inner join table_a b
on a.email_address = b.email_address and a.field_id <> b.field_id
where a.owner_id=10
order by a.field_id
Here is the example link:
http://sqlfiddle.com/#!9/5fbdf6/25/0
As per assumptions, first name has the field id 137 and last name has the field id 138.
You can try the following query to get the desired result.
SELECT CONCAT(SUBSTRING_INDEX(GROUP_CONCAT(`value`),",",1)," ",SUBSTRING_INDEX(GROUP_CONCAT(`value`),",",-1)) AS client_name
FROM Table_A
WHERE owner_id = 10
AND field_id IN (137, 138)
GROUP BY email_address;

SQL unwanted results in NOT query

This looks like it should be really easy question, but I've been looking for an answer for the past two days and can't find it. Please help!
I have two tables along the lines of
texts.text_id, texts.other_stuff...
pairs.pair_id, pairs.textA, pairs.textB
The second table defines pairs of entries from the first table.
What I need is the reverse of an ordinary LEFT JOIN query like:
SELECT texts.text_id
FROM texts
LEFT JOIN text_pairs
ON texts.text_id = text_pairs.textA
WHERE text_pairs.textB = 123
ORDER BY texts.text_id
How do I get exclusively the texts that are not paired with A given textB? I've tried
WHERE text_pairs.textB != 123 OR WHERE text_pairs.textB IS NULL
However, this returns all the pairs where textB is not 123. So, in a situation like
textA TextB
1 3
1 4
2 4
if I ask for textB != 3, the query returns 1 and 2. I need something that will just give me 1.
The comparison on the second table goes in the ON clause. Then you add a condition to see if there is no match:
SELECT t.text_id
FROM texts t LEFT JOIN
text_pairs tp
ON t.text_id = tp.textA AND tp.textB = 123
WHERE tp.textB IS NULL
ORDER BY t.text_id ;
This logic is often expressed using NOT EXISTS or NOT IN:
select t.*
from texts t
where not exists (select 1
from text_pairs tp
where t.text_id = tp.textA AND tp.textB = 123
);

Append string to a record's specified column after SELECT command

I have an sql command that returns me a list of duplicated items (in my MySQL database), only two columns, one for the duplicated value and one for the count of duplicated records.
SELECT title, COUNT(*) c FROM posts GROUP BY title HAVING c > 1
title c
---------------
title_1 2
title_a 2
title_b 2
I assume one result looks like this:(and it's an array of arrays)
objId title
------------
1 title_1
2 title_1
So my goal is to append a string to the second item of a result in the array of the duplicated record's like this:
objId title
------------
1 title_1
2 title_1_2
I've found a solution to update the record, but I don't have an idea how could I loop through the results that I get after the first sql command so I can't utilize it in practice.
UPDATE posts SET title = CONCAT(IFNULL(title,''), ' 2');
In pseudo code I would do something like this to create the new string for the title:
result[1].title = (oldTitleString," 2");
save result[1];
I'm new in sql and don't really know about the possibilities, maybe there would be an easier way to do it, so I would really appreciate if somebody could show me how can I get the second record from the duplicated item and extend it with another string.
My solution:
SELECT `objId`,`title`,
(SELECT CONCAT(`title`, '_', `po`.`objId`)
FROM `posts` `p`
WHERE `title` = `po`.`title` && `p`.`objId` < `po`.`objId` LIMIT 1) AS `title_custom`
FROM `posts` `po`
Here is sample fiddle:
http://sqlfiddle.com/#!9/a4164/8
Query looks like this:
select id, title,
concat(title,'_',
(select count(*) from posts p2 where p2.title = p1.title and p2.id <= p1.id)),
title,
count(*) c
from posts p1
group by title
having c > 1

Mysql multiple tables select

I've got a table, called for example, "node", from which I need to return values for as shown:
SELECT nid FROM node WHERE type = "book"
After I get a list of values let's say:
|**nid**|
|123|
|12451|
|562|
|536|
Then I need to take these values, and check another table, for rows where column 'path' has values as "node/123", "node/12451" (numbers the previous request returned) in one joined request. It all would be easier if collumn 'path' had simple numbers, without the 'node/'.
And then also count the number of identical i.e. 'node/123' returned.
End result would look like:
nid | path | count(path) | count(distinct path)
123 |node/123| 412 | 123
562 |node/562| 123 | 56
Works fine if done in multiple separated queries, but that won't do.
select a.nid from node a join othertable b
on b.path = concat("node/", a.nid) where type='book'
You can probably do something like the following (nid may require additional conversion to some string type):
SELECT *
FROM OtherTable
JOIN node ON path = CONCAT('node/', nid)
WHERE type = 'book'
Thank you all for your help. Basically, the problem was that I didn't know how to get nid and node/ together, but concat helped.
End result looks something like:
SELECT node.nid, accesslog.path, count(accesslog.hostname), count(distinct accesslog.hostname)
FROM `node`, `accesslog`
WHERE node.uid=1
AND node.type='raamat'
AND accesslog.path = CONCAT('node/', node.nid)
GROUP BY node.nid