Very simple mysql join - mysql

Anyone could tell me how to connect these 2 tables. I tried do it myself.. but just wasted a time, i know it's easy but I somehow can't understand it. Table is from my previous question
Table Articles:
ID Content
1 bla
2 blah
3 etc.
4 whatever
Table Similar:
ID Similar_ID
3 1
3 2
4 1
4 2
4 3

select a.ID,a.Content,s.Similar_ID from
Articles a inner join Similar s
on a.ID=s.ID

You want to browse the Similar table, and "convert" its IDs (e.g. 3) in Content (e.g. "Blah").
So:
SELECT * FROM Similar;
will list all similarities. Since we have two Ids to convert (something is similar to something else), we need two separate JOINS with the same table Articles, and we'll alias them to "a" and "b":
SELECT a.Content, b.Content
FROM Similar
JOIN Articles AS a ON (Similar.ID = a.ID)
JOIN Articles AS b ON (Similar.Similar_ID = b.ID)
;
The first JOIN "decodes" the ID field of Similar, the second decodes "Similar_ID".
So
3 1
becomes now
Etc. Blah
Or you can write:
SELECT CONCAT(a.Content, ' is similar to ', b.Content)
FROM... (same query as above)
and get
Etc. is similar to Blah
Blah is similar to whatever
...

Related

SQL queries - not getting the proper result from Like statement [duplicate]

This question already has answers here:
Is storing a delimited list in a database column really that bad?
(10 answers)
Closed 4 years ago.
Table name: student:
id name topics
--- ---- --------
1 Test1 1,2,10,15,25
2 Test2 5,21,11,18,13
3 Test3 2,1,16,25,10
4 Test4 2
My query:
select * from student where topics like '%2%'
output: all 4 records.
Expected: But i need to get only 3 record since that id 1,3,4 topics column contains 2. 2nd record doesn't contain 2 .
You can use the function FIND_IN_SET :
select * from student where FIND_IN_SET ('2', topics)
The second record DOES contain 2.
You need to use something like this.
WHere topics=2 or topics like '2,%'or topics like '%,2' or topics like '%,2,%'
The first checks if topics is 2. THe second if 2 is the first, but there are others. THe third checks if 2 is the last, but there are some numbers before, and the forth checks if 2 is somewhere in between
Something like that might help?
SELECT * FROM student WHERE topics LIKE '2,%' OR topics LIKE '%,2,%' OR topics LIKE '%,2' OR topics= '2';
its sad that you cant use IN with LIKE.

exact search and similar search combining two tables with multiple keywords mysql

Say I've two tables products and brands having below data.
tbl_products
ID Name BrandID Price
1 Keyboard 1 100
2 Keyboard 2 120
3 Keyboard wireless 1 130
4 Keyboard wireless 2 150
tbl_brands
ID Name
1 Microsoft
2 Dell
3 HP
What I want is when I type 'Microsoft Keyboard' or 'Keyboard Microsoft' then it should list me product ID 1 and 3 not 2 or 4 even 2 or 4 has keyboard. I may search for more keywords but it should give me only the items matching itself.
SELECT p.*, b.Name BrandName FROM tbl_products p INNER JOIN tbl_brands b ON b.ID = p.BrandID WHERE p.Name LIKE '%Microsoft%' OR b.Name LIKE '%Microsoft%' OR p.Name LIKE '%Keyboard%' OR b.Name LIKE '%Keyboard%'
Please help me to write proper MySQL query or any schema change with query..
Appreciate the question. Though I don't have exact answer but surely can discuss one approach to solve the problem.
STEP 1 Get BRAND NAME+NAME as single string.
STEP 2 Tokenise the entered STRING. Example Microsoft Keyboard = Mincrosoft,Keyboard Following Link for spliting the entered data. How do I split a string so I can access item x?
STEP 3 DO a like query on the string obtained in step 1.

Group join with many to one in one row

I would love some help. I'd like to join a one-to-many database and show all the info from one row in table 'post' with it's related meta (many). I can't seem to figure out how to do it.
Database called post:
ID Title
1 Hello world
2 Yeah buddy
3 This is a test
Database called meta:
ID postID Value
1 1 Testing testing
2 1 This is a value
3 2 Testing 123 testing
4 2 This is a value 23
5 3 Testing testing test
6 3 This is a value yeah
I would like to group the results for my query as follows:
1 Hello world Testing testing This is a value
2 Yeah buddy Testing 123 testing This is a value 23
3 This is a test Testing testing test This is a value yeah
MySQL Query (so far):
SELECT DISTINCT p.title, m.*
FROM post p
LEFT JOIN meta m ON p.ID = m.postID
GROUP BY p.title
Only the output given is:
1 Hello world Testing testing
2 Yeah buddy Testing 123 testing
3 This is a test Testing testing test
Which is really frustrating because I would like to show all the related fields, but I can't seem to figure out what's wrong. It seems the 'Value'-column can't exist twice per row...
Can somebody please help (or point me in the right direction?)
Would it work for you if values are combined?
SELECT p.title, group_concat(m.value separator ",") as values
FROM post p
LEFT JOIN meta m ON p.ID = m.postID
GROUP BY p.title

MySQL multiple intersection with self performance

For simplicity, let's say we have a table with two columns: uid (user id) and fruit, describing what kinds of fruit a user likes.
E.g.:
uid | fruit
----|------------
1 | Strawberry
1 | Orange
2 | Strawberry
2 | Banana
3 | Watermelon
and so forth.
If I want to find what kinds of fruit are common in N particular users (i.e. the intersection N times of the table with itself), the first option is to use an INNER JOIN.
SELECT DISTINCT fruit FROM Fruits f1
INNER JOIN Fruits f2 USING (fruit)
INNER JOIN Fruits f3 USING (fruit)
...
INNER JOIN Fruits fN USING (fruit)
WHERE f1.uid = 1 AND f2.uid = 2 ... AND fN.uid = M
But this kinds of looks silly to me. What if N = 10? or even 20? Is it sensible to do 20 joins? Is there some other join operation I'm missing?
Before learning the "magic" of joins, I used another method, which would apply in my current case as follows:
SELECT DISTINCT fruit FROM Fruits
WHERE uid IN (1, 2, ..., M)
GROUP BY fruit
HAVING COUNT (*) = N
It seems much more compact, but I remember somebody telling me to avoid using GROUP BY because it is slower than an INNER JOIN.
So, I guess my question really is, is there maybe a third method for doing the above? If yes/no, which one is the most efficient?
-- EDIT --
So, it seems a question has been asked before, bearing a resemblance to mine. The two answers provided, are actually the two methods I'm using.
But the question remains. Which one is really more efficient? Is there, maybe, a third one?

GROUP BY does not remove duplicates

I have a watchlist system that I've coded, in the overview of the users' watchlist, they would see a list of records, however the list shows duplicates when in the database it only shows the exact, correct number.
I've tried GROUP BY watch.watch_id, GROUP BY rec.record_id, none of any types of group I've tried seems to remove duplicates. I'm not sure what I'm doing wrong.
SELECT watch.watch_date,
rec.street_number,
rec.street_name,
rec.city,
rec.state,
rec.country,
usr.username
FROM
(
watchlist watch
LEFT OUTER JOIN records rec ON rec.record_id = watch.record_id
LEFT OUTER JOIN members usr ON rec.user_id = usr.user_id
)
WHERE watch.user_id = 1
GROUP BY watch.watch_id
LIMIT 0, 25
The watchlist table looks like this:
+----------+---------+-----------+------------+
| watch_id | user_id | record_id | watch_date |
+----------+---------+-----------+------------+
| 13 | 1 | 22 | 1314038274 |
| 14 | 1 | 25 | 1314038995 |
+----------+---------+-----------+------------+
GROUP BY does not "remove duplicates". GROUP BY allows for aggregation. If all you want is to combine duplicated rows, use SELECT DISTINCT.
If you need to combine rows that are duplicate in some columns, use GROUP BY but you need to to specify what to do with the other columns. You can either omit them (by not listing them in the SELECT clause) or aggregate them (using functions like SUM, MIN, and AVG). For example:
SELECT watch.watch_id, COUNT(rec.street_number), MAX(watch.watch_date)
... GROUP by watch.watch_id
EDIT
The OP asked for some clarification.
Consider the "view" -- all the data put together by the FROMs and JOINs and the WHEREs -- call that V. There are two things you might want to do.
First, you might have completely duplicate rows that you wish to combine:
a b c
- - -
1 2 3
1 2 3
3 4 5
Then simply use DISTINCT
SELECT DISTINCT * FROM V;
a b c
- - -
1 2 3
3 4 5
Or, you might have partially duplicate rows that you wish to combine:
a b c
- - -
1 2 3
1 2 6
3 4 5
Those first two rows are "the same" in some sense, but clearly different in another sense (in particular, they would not be combined by SELECT DISTINCT). You have to decide how to combine them. You could discard column c as unimportant:
SELECT DISTINCT a,b FROM V;
a b
- -
1 2
3 4
Or you could perform some kind of aggregation on them. You could add them up:
SELECT a,b, SUM(c) "tot" FROM V GROUP BY a,b;
a b tot
- - ---
1 2 9
3 4 5
You could add pick the smallest value:
SELECT a,b, MIN(c) "first" FROM V GROUP BY a,b;
a b first
- - -----
1 2 3
3 4 5
Or you could take the mean (AVG), the standard deviation (STD), and any of a bunch of other functions that take a bunch of values for c and combine them into one.
What isn't really an option is just doing nothing. If you just list the ungrouped columns, the DBMS will either throw an error (Oracle does that -- the right choice, imo) or pick one value more or less at random (MySQL). But as Dr. Peart said, "When you choose not to decide, you still have made a choice."
While SELECT DISTINCT may indeed work in your case, it's important to note why what you have is not working.
You're selecting fields that are outside of the GROUP BY. Although MySQL allows this, the exact rows it returns for the non-GROUP BY fields is undefined.
If you wanted to do this with a GROUP BY try something more like the following:
SELECT watch.watch_date,
rec.street_number,
rec.street_name,
rec.city,
rec.state,
rec.country,
usr.username
FROM
(
watchlist watch
LEFT OUTER JOIN est8_records rec ON rec.record_id = watch.record_id
LEFT OUTER JOIN est8_members usr ON rec.user_id = usr.user_id
)
WHERE watch.watch_id IN (
SELECT watch_id FROM watch WHERE user_id = 1
GROUP BY watch.watch_id)
LIMIT 0, 25
I Would never recommend using SELECT DISTINCT, it's really slow on big datasets.
Try using things like EXISTS.
You are grouping by watch.watch_id and you have two results, which have different watch IDs, so naturally they would not be grouped.
Also, from the results displayed they have different records. That looks like a perfectly valid expected results. If you are trying to only select distinct values, then you don't want ot GROUP, but you want to select by distinct values.
SELECT DISTINCT()...
If you say your watchlist table is unique, then one (or both) of the other tables either (a) has duplicates, or (b) is not unique by the key you are using.
To suppress duplicates in your results, either use DISTINCT as #Laykes says, or try
GROUP BY watch.watch_date,
rec.street_number,
rec.street_name,
rec.city,
rec.state,
rec.country,
usr.username
It sort of sounds like you expect all 3 tables to be unique by their keys, though. If that is the case, you are simply masking some other problem with your SQL by trying to retrieve distinct values.