How to compare a value with a csv value in mysql? - mysql

Table 1
id(int) | name(varchar)
1 | at,bat
2 | cat,at,bat,mat
3 | mat,cat
4 | sat,bat
Table 2
id(int) | type(varchar)
1 | at
2 | mat
As you can see table1 contains csv strings. Now I need to fetch the ids from Table 1 whose names exist in Table2 type field.
Is there any pure mysql query way of doing this? if not, what would be the most time efficient way of doing this in case of large record sets?

I would use FIND_IN_SET(str,strlist):
select distinct t1.id
from table1 t1
join table2 t2 on find_in_set(t2.type, t1.name) > 0
Working example: http://sqlfiddle.com/#!2/b642c/4

See here
select a.ids as id1, b.ids as id2, a.name,b.type
from table1 a
inner join table2 b on find_in_set(b.type,a.name)

Related

Seperate comma and get value from another table and concatenate result value

Suppose firstly my table1 is:
id name
----------
1 abc
2 bcd
3 cde
In table2 i store
id table1_id
------------
1 1,2
2 1,3
3 1,2,3
I want output like this
id table1_value
----------------
1 abc,bcd
2 abc,cde
3 abc,bcd,cde
Please help me in with mysql query..
Below is a query which should meet your requirements. As #GurV commented above, you should avoid storing CSV data in your table, which is not normalized, and which thwarts much of the power which MySQL has as a relational database.
SELECT t2.id,
GROUP_CONCAT(t1.name ORDER BY t1.name) AS table1_value
FROM table2 t2
INNER JOIN table1 t1
ON FIND_IN_SET(t1.id, t2.table1_id) > 0
GROUP BY t2.id
Output:
Demo here:
Rextester

MySQL, get all rows describing one product from table 1, by their references in table 2

I need to find all attributes & image(s) for a product.
Every product is marked as such in the column type in Table 1.
The attributes are also defined in Table 1, each attribute on a seperate row.
This is a simplified version of the table structures:
Table 1:
id | type | value | url
1 | product | T-shirt |
2 | image | | http://www......
........
15 | size | XXL |
........
18 | color | blue |
Table 2:
id | ref_id | link_id
1 | 1 | 1
2 | 1 | 2
3 | 1 | 15
4 | 1 | 18
The relationship between a product and its attributes is defined in Table 2:
- ref_id matches the id in Table 1 for the product we want
- link_id holds an id (from Table 1) which is either the product itself or an attribute of the product
So in this example, id 1 in Table 1 has 4 occurences in Table 2 (ref_id = 1): the product row and 3 attribute rows (image, size & color)
They are referenced by the column link_id in Table 2.
I would like to solve this in 1 query if possible, but I am stuck at how to solve the 'back-reference'.
Once I have found a product's id in Table 1, I can get the link_id's in Table 2 allright, but how do I use those again (in the same query) to get the rows from Table 1.
Is this at all possible in 1 query, or should I use 2 seperate queries for this?
UPDATE:
this is how far I have come:
SELECT t1.id, t1.type, t1.value, t1.url,
t2.link_id
FROM table_1 t1
LEFT JOIN table_2 t2
ON t1.id = t2.ref_id
WHERE t1.type = 'product'
But after that I don't know how to construct the rest of the query based on the 'back-reference'.
You can join back to table_1 again
SELECT t1.id, t1.type, t1.value, t1.url,
t2.link_id, t1_attributes.type, t1_attributes.value
FROM table_1 t1
LEFT JOIN table_2 t2
ON t1.id = t2.ref_id
LEFT JOIN table_1 t1_attributes ON t2.link_id = t1_attributes.id
WHERE t1.type = 'product'
This will get you 1 row for each attribute though. If you want a field for each type of attribute, you'll have to do a join for each one.
SELECT t1.id, t1.type, t1.value, t1.url,
t2.link_id, t1_image.value, t1_size.value
FROM table_1 t1
LEFT JOIN table_2 t2 ON t1.id = t2.ref_id
LEFT JOIN table_1 t1_image ON t2.link_id = t1_image.id
LEFT JOIN table_1 t1_size ON t2.link_id = t1_size.id
WHERE t1.type = 'product' AND t1_image.type = 'image' AND
t1_size.type = 'size'

Remove all query results that have duplicates (NOT DISTINCT)

I have a table with two sets of integer values. Using MySQL I want to display all of the rows that correspond to unique entries in the second column. Basically I can have duplicate A values, but only unique B values. If there are duplicates for a value in B, remove all the results with that value. If I use DISTINCT I will still get one of those duplicates which I do not want. I also want to avoid using COUNT(). Here's an example:
|_A____B_|
| 1 2 |
| 1 3 |
| 2 2 |
| 2 4 |
| 1 4 |
| 5 5 |
Will have the following Results (1,3), (5,5). Any value in B that has a duplicate is removed.
Try this
SELECT * FROM TEMP WHERE B IN (
SELECT B FROM TEMP GROUP BY B Having COUNT(B)=1
);
I know you want to avoid using COUNT() but this is the quick solution.
working fiddle here - http://sqlfiddle.com/#!9/29d16/8
Tested and works! you need atleast count(*) to count the values
select * from test where B in (
select B from test group by B having count(*)<2
)
I don't know why you want to avoid using count(), because that's what would do the trick as follows:
Let's say your table is named "mytable"
SELECT t1.A, t1.B
FROM mytable t1
JOIN (
SELECT B, count(*) AS B_INSTANCES
FROM mytable
GROUP BY B
HAVING count(*) = 1
) t2 ON t2.B = t1.B
ORDER BY t1.A, t1.B

selecting one column from 3 different tables

I have 3 tables:
Table 1: columns are:
+------+-------+----------+----------+
| date | time | user_id | channel |
+------+-------+----------+----------+
Table 2:
+---------+------------+
| user_id | id _number |
+---------+------------+
Table 3:
+---------+-------+
| channel | sort |
+---------+-------+
In table 1 the columns are sorted as following :
2011-07-29, 12:35:15.650, 22, DeluxeMusic
In table 2 :
130.83.10.c42ce82365b9f6d , 22 (same as user_id in table 1)
In table 3:
DeluxeMusic (same as in table 1), entertainment.
The columns user_id in table 2 : 130.83.10.c42ce82365b9f6d means a user_id of some user. From this user ID I need to get all entries with the value of 130 in the begining. For all entries with same value 130.
Then I need to seek for this value of 130 in the table 3 the sort of channel they are watching, and to count by that all users watching a channel typ.
Channel typs are also : sport, shopping, entertainment and so on.
you could try this too:
select count(*) from t1 join t2 on t1.id = t2.id and t2.userid like '130%' join
t3 on t1.channel = t3.channel group by t1.channel
sql fiddle here
Edit:
another version:
select count(t1.id) , t1.*, t2.*, t3.*
from t1 join t2 on t1.id = t2.id join
t3 on t1.channel = t3.channel and t2.userid
like '130%' group by t3.channel, t1.id
fiddle
Not sure if I get your question completely. But from what I understand you would be needing something like below:
SELECT COUNT (*) FROM TABLE1 T1,TABLE2 T2,TABLE3 T3
WHERE T1.USER_ID = T2.USER_ID
AND T1.USER_ID LIKE '130%'
AND T1.CHANNEL = T3.CHANNEL
The above sql would be the used to fetch the count of the channels that the users with their use ids beginning with '130' would be watching.
Hopefully this should help you in someway.

SQL count each distinct value in column and add name from another table where the ID matches

My SQL Skills are next to none. After looking around for the past 2 hours trying to figure this out I need some help please.
I have 2 tables as below
Table1 Table2
ID | Name Status_id
----------- ----------
1 | Open 1
2 | Closed 2
3 | On-Hold 1
What I would like to do is count the status_id in table 2 and group by the status_id. Then add the Name where the ID matches in the first column.
What I have at the moment is
SELECT status_id, COUNT(*) AS 'num' FROM table2 GROUP BY status_id
This is great so far and returns
1 | 2
2 | 1
What I need to return is
Open | 2
Closed | 1
I hope that is clear. Can anyone help?
Many thanks!
SELECT a.name, COUNT(*) AS num FROM table2 b
INNER JOIN table1 a
ON b.status_id=a.id
GROUP BY status_id
In the case that you want to also have Zero for On-Hold you'd need to do a LEFT join and count the a column from table2 instead of *
SELECT t1.name,
Count(t2.Status_id) AS num
FROM table1 t1
LEFT JOIN table2 t2
ON t1.id = t2.Status_id
GROUP BY t1.name;
DEMO