I have a two tables one for news items and one for images.
News Table Structure
ID - numeric
newstitle - text
newsdesc - text
newsimages - text
Image Table Structure
ID - numeric
medianame - text
So a common news record would be:
ID = 1, newstitle="asdasfa", newsdesc="afsdgsgs", newsimages="1,2"
And the image table record would be:
ID=1, medianame="image.jpg"
I am trying to create a select statement that reads the data from the news table but provides me with the image name from the image table instead of the IDs.
If there is anything else ive left out let me know
Thanks
You can use FIND_IN_SET function
Example:
SELECT `news`.`ID`, `news`.`newstitle`, `news`.`newsdesc`,
GROUP_CONCAT(`images`.`medianame` SEPARATOR ',') AS `newsimages`
FROM `news`
LEFT JOIN `images` ON FIND_IN_SET(`images`.`ID`,`news`.`newsimages`)
GROUP BY `news`.`ID`
P.S. if you have (or planning to have) a big amount of rows, then you must to normalize the data.
it seems to be simple
SELECT N.*, I.medianame FROM News_Table N left join Image_Table I
ON N.Id=I.Id
I have assumed that tables names are News_table and Image_table respectively and that one news piece may have more than one image.
Related
I'm working on a mysql database select and cannot find a solution for this tricky problem.
There's one table "words" with id and names of objects (in this case possible objects in a picture).
words
ID object
house
tree
car
…
In the other table "pictures" all the information to a picture is saved. Besides to information to resolution, etc. there are especially informations on the objects in the picture. They are saved in the column objects by the ids from the table words like 1,5,122,345, etc.
Also the table pictures has a column "location", where the id of the place is written, where I took the picture.
pictures
location objectsinpicture ...
1 - 1,2,3,4
2 - 1,5,122,34
1 - 50,122,345
1 - 91,35,122,345
2 - 1,14,32
1 - 1,5,122,345
To tag new pictures of a particular place I want to become suggestions of already saved information. So I can create buttons in php to update the database instead of using a dropdown with multiple select.
What I have tried so far is the following:
SELECT words.id, words.object
FROM words, pictures
WHERE location = 2 AND FIND_IN_SET(words.id, pictures.objectsinpicture)
GROUP BY words.id
ORDER BY words.id
This nearly shows the expected values. But some information is missing. It doesn't show all the possible objects and I cannot find any reason for this.
What I want is for example all ids fo location 2 joined to the table words and to group double entries of objectsinpicture:
1,5,122,34
1,14,32
1,5,14,32,34,122
house
...
...
...
...
...
Maybe I need to use group_concat with comma separator. But this doesn't work, either. The problem seems to be where condition with the location.
I hope that anyone has an idea of solving this request.
Thanks in advance for any support!!!
This is a classic problem of denormalization causing problems.
What you need to do is store each object/picture association separately, in another table:
create table objectsinpicture (
picture_id int,
object_id int,
primary key (picture_id, object_id)
);
Instead of storing a comma-separated list, you would store one association per row in this table. It will grow to a large number of rows of course, but each row is just a pair of id's so the total size won't be too great.
Then you can query:
SELECT w.id, w.object
FROM pictures AS p
JOIN objectsinpicture AS o ON o.picture_id = p.id
JOIN words AS w ON o.object_id = w.id
WHERE p.location = 2;
I need to insert data into a set of columns in data_table (table 1) from alarm_status_log_table (table 2, the whole thing), and another set of data into data_table (table 1) from channel table (table 3, just name and description), thus completing data_table (table 1).
But the problem is, the name & description columns which I need to pass onto data_table must be on the same row as the alarm_id they correspond with. That alarm_id is the same as the channel_id from the channel table which happens to already have the name and description that I want to send to data_table.
Basically I want to say:
Insert (name, description) from channel(table 3) into data_table(name, description) where channel_id = alarm_id
How can I proceed?
It is possible to make an update JOIN like this:
UPDATE data_table a
INNER JOIN table3 b ON a.alarm_id = b.channel_id
SET a.name=b.name, a.description=b.description
If you do not want to update, can you just join the tables? Maybe it would be better to create a joined view; this would avoid having redundant inconsistent data.
All i needed to do was to use a VIEW, since reordering data coming from two tables into a third table is quite tricky, here is the script i used to get the view i wanted:
SELECT channel.name, channel.description, alarm_status_log.*
FROM data2desk.alarm_status_log
LEFT JOIN data2desk.channel ON channel.channel_id=alarm_status_log.alarm_id
And it did the trick :)
final view
I have two tables, one that holds lot of links (tvlinks), and another that holds list of substrings to be matched against the name of the links (tvshows):
tvlinks:
id (int 11) - primary index key
name (text) - name of the tv show link
link (text) - link to a website with information about the tv show
tvshows:
id (int 11) - primary index key
name (text) - name of the tv show
match (text) - substring to be matched against name in tvlinks table
there can be multiple rows in tvlinks with exactly the same name and different link. There is no duplicate rows.
i use the following query to get all rows from tvlinks where tvshows.match is a substring of tvlinks.name:
SELECT l.id,
l.name,
l.link
FROM tvlinks tvl
INNER JOIN tvshows tvs
ON ( INSTR(tvl.name, tvs.match )
ORDER BY tvl.name
;
and it works fine, my problem is that i'd like to put together another query that would return only the rows that do not get matched by the query above.
i've been bashing my head on the keyboard on and off for a week or two, and i'm sure its something really simple that i'm missing in a big way. :)
Thanks for your help
select id from tvlinks where id not in (select l.id,
FROM tvlinks tvl
INNER JOIN tvshows tvs
ON ( INSTR(tvl.name, tvs.match )
ORDER BY tvl.name
;)
Not efficient per se, all depends on your tables.
INSTR() - Return the index of the first occurrence of substring - not the condition you need
I have a table on my database that lists different sections to show. We only want to show the sections if the user ID is inside a column of the database called 'userAccess' which will have a comma seperated list of the users who can see it.
Example row
id section userAccess
1 editNews 1,13,15
So how can I query that out and say something like
SELECT `section` WHERE '$userID' is in `userAccess`
I tried LIKE %, but obviously that will return all 3 users if I do LIKE %1%.
SELECT `section` WHERE FIND_IN_SET('$userID', `userAccess`) != 0
You could consider moving to a groups based permissioning structure, then have a GroupAccess table, with an FK to your section and the group ID. Users would be assigned to a Group in a UserGroup link table. This provides you with a lot of flexibility (but more complexity).
Or failing that, simply have
id section userAccess
1 editNews 1
2 editNews 13
3 editNews 15
Another alternative:
SELECT `section`
FROM t
WHERE concat(',', '$userID', ',') like concat(',', `userAccess`, ',')
In other words, you can use like if you put the separator around the two strings. I offer this because it is more similar to the solution you tried and you can use the same approach in other databases.
I have a table named product, where in the category field I have inserted around 5 to 6 categories.
For example 2,3,4,5,12 just like that.
But when I use this query it doesn't work:
SELECT * FROM product WHERE category in '3'
SELECT * FROM `product` WHERE `category` LIKE '%3%'
can anyone help to fix it
SELECT * FROM product WHERE FIND_IN_SET('3',category);
See: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set
If you don't have find_in_set this code would be equivalent:
SELECT * FROM product
WHERE category = '3' or category LIKE '%,3,%'
or category LIKE '3,%' or category LIKE '%,3';
Otherwise you will get a false positive for 3 on '13, 23, 40'.
Warning
Do note however that it's very bad practise to put a CSV list in a field.
You'll get much better performance by extracting the list out of the field and putting it in another table in a 1-to-N relation.
the best practice would be to create another table!
i.e.:
product_categories
int productid
int category
SELECT * FROM product p
INNER JOIN product_categories pc ON pc.productid = p.productid
WHERE pc.category = '3'
with the way you want to implement it, you would also have a problem when a category '13' is available, but you want to have '3'
I'm sorry to say it but you should redesign your database.
Using a single field to store multiple connections will always be a pain in the butt.
It is much easier to create an additional table that stores the relations.
The IN statement wont work because you are asking for the category to be an exact match of "3" when it is in fact "2,3,4,5,12". I think it should also be in round brackets.
As user737767 said you should really normalise your database so you have a table of categories, a table of products and another table to show which categories each product belongs to.
Your LIKE statement is also a bad idea because searching for "3" will also bring back results like "23"