MySQL - How to select only results with certain words in them? - mysql

I got user profiles on my page. In database, every user has column "mixes", where they put links to their dj mixes. It´s type is varchar.
What Im trying to do: I want to add a "panel" on my homepage, where there´ll be two randomly selected embed dj mixes from the database. Catch is, that some users don´t have filled anything in their "mixes" section, and some of them are using simple links - I want to display only embed mixcloud or soundcloud players, simple link wouldn´t look nice there.
My problem is I don´t know how to handle this by SQL query.
In overall Im looking for query which:
selects 2 random users
they must be users with not empty "mixes" column
in the "mixes" column there must be iframe tag
I don´t know how to explain it better... SQL would be like:
SELECT mixes FROM djs
WHERE mixes IS NOT NULL
AND mixes contains "iframe"
ORDER BY RAND()
LIMIT 2

You must be looking for a LIKE for a match.
SELECT mixes FROM djs
WHERE mixes IS NOT NULL
AND mixes like '%iframe%'
ORDER BY RAND()
LIMIT 2
Refer to:
MySQL: Pattern Matching: LIKE operator

Related

Why DB Browser have an order I can't replicate?

I have an issue I really don't understand. In fact, I have a database of movies where there's a table for actors,containing two colums (movie id and name).
For example, then I enter the movie id of Django Unchained, the first result is Jamie Fox (the main actor).
But then I enter, this sql query (i would expect to get Jamie Fox, Christoph and Leonardo):
SELECT * FROM LesActeurs WHERE film_id=68718 ORDER BY acteur LIMIT 3
But I get 3 actors by alphabetical order. Do You Know how could I mimic the DB Browser order with command (I'm a beginner)?
Thank you!
Without any other column to order by, you can't get that result, at least not reliably. Without an explicit order by clause, the database is free to return the rows in whatever order it chooses (often it's just the order in which they were inserted).
If you want to get reliably get Jamie, Christophe and Leonardo you could add another column (e.g., "importance"), populate it and then query and explicitly order by it.

Repeatable Multi-Colum Data Rows in Wordpress Custom Post Type

I'm moving a sports website from .asp to wordpress.
I have two custom post types:
Players
Tournaments
I need to be able to enter scores into the tournaments for players from the player post type.
The scoring tablulation is as follows:
Player ID First Name Last Name City State Points Place Scores
And I need to be able to add more rows, selecting the players to add the above info for.
The current ASP tables look like this, for each tournament:
And I need to be able to add unlimited rows (repeater).
It would be easy if it was just one column, I could use something like Advanced Custom Fields repeater field, but I do not know how to add rows of related multi-column data, which I can then query and display on the front-end.
Also, I would make each scoring row it's own post, but it would be waaay too many posts.
What I want, is for each tournament (stored in the tournaments CPT), to be able to add the scoring rows there, selecting the player from the player post type, and filling out the columns, as seen, with the ability to add as many rows as there are players for each tournament.
Thank you for your help follow programmers! I've been doing this a fairly long time, but this is a new use-case for me.
You can use Meta Box Group plugin. It allows you to create repeatable group of fields.
So, in your situation, you need to create a group of player (post field), first name, last name, city, state, points, place, score. Then make the whole group repeatable. (In Meta Box, it uses another term clone).

In MySQL is there a way to chose one column over another when doing SELECT *?

Ok, for a moment, throw out of your mind "good database design". Let's say I have two tables, and they have some of the same columns.
item
-------
id
title
color
and
item_detail
-------
id
weight
color
In a good normal query, you'd choose the columns you want within the query, like so:
SELECT item.title, item_detail.color, item_detail.weight ...
But what if you are stuck with a query that was built with star/all:
SELECT * ...
In this case you would get two color columns pulled back in your results, one for each table. Is there a way in MySQL to chose one color column over the other, so only one shows up in the results, without a full rewrite of the statement? So that I could say that the table item_detail takes priority?
Probably not but I thought I'd ask.
Err. No there is not.
But define "without a full rewrite of the statement". As far as I can see you'd just need to rewrite the select * portion of the query.
If you cannot touch the statement at all, then you are free to ignore the column in your application (the order of the columns does not change between calls)... or you could create a view...
It's hard to know which constraints you are dealing with when you say "But what if you are stuck with a query".

Count the number of times keywords (in a table) appear in a field in another table

I will simplify my problem in order to explain it.
I have a table which contains text messages posted by users and another table which contains keywords.
I want to display, for each user, the number of times keywords are found in text messages.
I don't want the result to display a keyword if it's not found in text messages.
I wan't it to be case INSENSITIVE. All keywords are lowered but in messages, you can find lower & upper chars.
Because I'm not sure that my explanation is clear enough, here comes the SQLFiddle.
http://sqlfiddle.com/#!2/c402a
Hope anyone can help me.
I found what I was looking for. It wasn't easy for me but here is my query :
SELECT t_msg.msg_usr,
t_list.list_word,
count(t_list.list_word),
t_msg.msg_text
FROM t_msg
INNER JOIN t_list
ON LOWER(t_msg.msg_text) LIKE CONCAT("%", t_list.list_word, "%")
GROUP BY t_msg.msg_usr, t_list.list_word;
The SQLFiddle is there : http://sqlfiddle.com/#!2/ba052/8
The recommendation would be to not try solving this with a query. It's possible to write a query that will do it, such query will scan the messages table for each keyword separately, and produce a count (or a row that you can group by), but this won't scale, or be reliable in sense of language search.
Here is what you might want to do:
Create a table to map (user_id, keyword_id) to a count of this keyword in messages of this user. Let's call it t_keyword_count.
Each time you receive a message, before you save the message into the database, search it for all the keywords you care about (using whatever good text search libraries that account for misspellings, etc.). You should know the (user_id) for this message.
You will, at that point, be ready to add the message to the database, and will have an array of (keyword_id) with keywords that this message will have.
In a transaction, insert the message into the t_msg table, and run update/insert for (user_id,keyword_id) to have value=value+1 (or +n, if you need to count the same keyword more than once in the same message) for the t_keyword_count table.
If you are trying to solve the problem of having to do the above on existing data, you can do this manually, just to build up that t_keyword_count table first (depends on how many keywords you have in total, but even if there are a lot, this can be scripted). But you should change (or mirror) the t_msg.msg_text field to be a field suitable for text search, and use SQL text search functionality to find the keywords.

Table join--multiple rows to/ from one column (/ cell)

I have searched for a solution for this problem, but haven't found it (yet), probably because I don't quite know how to explain it properly myself. If it is posted somewhere already, please let me know.
What I have is three databases that are related to each other; main, pieces & groups. Basically, the main database contains the most elementary/ most used information from a post and the pieces database contains data that is associated with that post. The groups database contains all of the (long) names of the groups a post in the main database can be 'posted in'. A post can be posted in multiple groups simultaneously. When a new post is added to my site, I check the pieces too see if there are any duplicates (check if the post has been posted already). In order to make the search for duplicates more effective, I only check the pieces that are posted in the same group(s).
Hopefully you're still with me, cause here's where it starts to get really confusing I think (let me know if I need to specify things more clearly): right now, both the main and the pieces database contain the full name of the group(s) (basically I'm not using the groups database at all). What I want to do is replace the names of those groups with their associated IDs from the groups database. For example, I want to change this:
from:
MAIN_table:
id  |  group_posted_in
--------|---------------------------
1   | group_1, group_5
2   | group_15, group_75
3   | group_1, group_215
GROUPS_table:
id  |  group_name
--------|---------------------------
1   | group_1
2   | group_2
3   | group_3
etc...
into:
MAIN_table:
id  |  group_posted_in
--------|---------------------------
1   | 1,5
2   | 15,75
3   | 1,215
Or something similar to this. However, This format specifically causes issues as the following query will return all of the rows (from the example), instead of just the one I need:
SELECT * FROM main_table WHERE group = '5'
I either have to change the query to something like this:
...WHERE group = '5' OR group = '5,%' OR group = '%,5,%' OR group = '%,5'
Or I have to change the database structure from Comma Separated Values to something like this: [15][75]. The accompanying query would be simpler, but it somehow seems like a cumbersome solution to me. Additionally, (simple) joins will not be easy/ possible at all. It will always require me to run a separate query to fetch the names of the groups--whether a user searches for posts in a specific group (in which case, I first have to run a query to fetch the id's, then to search for the associated posts), or whether it is to display them (first the posts, then another query to match the groups).
So, in conclusion: I suppose I know there is a solution to this problem, but my gut tells me that it is not the right/ best way to do it. So, I suppose the question that ties this post together is:
What is the correct method to connect the group database to the others?
For a many-to-many relationship, you need to create a joining table. Rather than storing a list of groups in a single column, you should split that column out into multiple rows in a separate table. This will allow you to perform set based functions on them and will significantly speed up the database, as well as making it more robust and error proof.
Main
MainID ...
Group
GroupID GroupName
GroupsInMain
GroupsInMainID MainID(FK) GroupID(FK)
So, for MainID 1, you would have GroupsInMain records:
1,1,1
2,1,5
This associates groups 1 and 5 with MainID 1
FK in this case means a Foreign Key (i.e. a reference to a primary key in another table). You'd probably also want to add a unique constraint to GroupsInMain on MainID and GroupID, since you'd never want the same values for the pairing to show up more than once.
Your query would then be:
select GroupsInMain.MainID, Group.GroupName
from Group, GroupsInMain
where Group.GroupID=GroupsInMain.GroupID
and Group.GroupID=5