SQL one column multiple values [duplicate] - mysql

This question already has answers here:
Query with multiple values in a column
(4 answers)
Closed 6 years ago.
Hi I'm not sure how to even formulate this question but I'll try my best.
I have a table called games, in this table there's 3 columns, ID (INT), epoch (INT) and users (TEXT), now in each users column there is values from 4 to 25 values separated by a comma, the values are from 1 to 6 characters, so for instance:
ID, EPOCH, USERS
1, 1461779167, (123, 58234, 548245, 225122)
2, 1461774823, (326784, 54235, 6373, 3566, 384174)
3, 1461773423, (326784, 542355, 234, 351)
Now my problem is I need to fetech only ONE among the users let's say I need to fetch the "user" 54235, it cannot be CONTAINS because it would collide with 542355 so what should I do? How should I properly arrange these columns to avoid such situations or to simplify it in general?

A "proper arrangement" of these columns requires some normalization.
You could have a second table, called something like "player_games", which consists of:
Columns id, game, player
Then you associate a user with a game by inserting into player_games.
So if player 2 is associated with game 5, you do:
INSERT INTO player_games (game, player) VALUES (5, 2);
And then, if you need to get all games associated with player 2:
SELECT game FROM player_games WHERE player = 2;
And if you need to get all players associated with game 5:
SELECT player FROM player_games WHERE game = 5;

simplest hack you can do is instead of matching "54235" you can match "54235,". match comma as well and it will do the trick.
make sure you columns comma arrangement is proper atleast.
but this is not the right way to store results. you should have different table for mapping.

Related

How to select comma-separated values from a field in one table joined to another table with a specific where condition?

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;

Get common data based on multiple fields in mysql [duplicate]

This question already has answers here:
SELECTING with multiple WHERE conditions on same column
(12 answers)
Closed 1 year ago.
I don't know if the question title is so clear, but here is my question:
I had table UsersMovements which contains Users along with their movements
UsersMovements:
ID
UserID
MovementID
Comments
I need help looking for a query which would give me if users 1, 2 & 3 had been in a common MovementID, knowing that I had know what is the MovementID
The real case is that I want to see if those X users which I would select been in an area (in a limited interval, assuming I had date/Time in the table)
Thank you
The following returns all movement ids that have all three users:
select movementid
from usermovements
where userid in (1, 2, 3)
group by movementid
having count(distinct userid) = 3

SQL Query Design Help: Finding duplicates in multiple tables & exclusions

I am trying to design a query that picks up duplicate records from across two tables based on a few fields. I've set up what I've done so far here: http://sqlfiddle.com/#!2/e36c8d/1/0
Some context:
1) These two tables identified below house 'items' for a game that players play. Items come from either drops from monsters/player trades.
2) Players in the game are identified by their CharID
3) Items are primarily defined by the following unique fields: Name, ItemID, ID1, ID2, ID3.
4) There are other attributes for each item, but these can be changed depending on what the player does (e.g. changes colour of item; moves it position, upgrades it).
5) There are two tables where items are stored: ITEM and BANKITEM. Item = bag; Bankitem = warehouse.
There are occasions where players can (accidentally, or intentionally) duplicate individual items and then trade those items to other players or use on another one of their characters.
Needs (Really important to meet all 3 needs):
1) I need the query to scan both tables simultaneously to identify items that have duplicate Name, ItemID, ID1, ID2, ID3 that I can then investigate further (and delete one of the duplicates).
2) I need the query to exclude certain items based on Name (e.g., RedPotions all have the same Name, ItemID, ID1, ID2, and ID3. These are common items and duplicates are fine...I don't need them included in the listing as they are not rare/high value items).
3) I need the query to exclude CharID that are NULL (This is where I am having real difficulty because CharID is not part of my SELECT statement, and it can't be because it is entirely possible for two different CharIDs to have the same duplicate rare item).
SQL FIDDLE:
If the query was working properly, the results should show:
2 duplicate ChainHose(M) with the following common fields: ChainHose(M), 100, 17089, 22452, -12225
The ChainHose(M) with the CharID of '0' would be excluded from the listing. Note the actual field in the table is NULL and not '0'. (I am new to SQL/SQL Fiddle and wasn't sure how to make it 'NULL' in SQL Fiddle for example purposes.
2 duplicate Hauberk(W) with the following common fields: Hauberk(W), 200, 12369, 15252, 95682. It doesn't matter that the colour and lifespan are different (player with the duplicate could have dyed the armour after obtaining the duplicated item. The lifespan could have been reduced through use).
Does anyone have any advice? I've previously asked a similar question without resolve (see Advanced SQL Query Design Help (Duplicates across two tables, multiple fields, possible exclusions based on one field)). The person recommended I be more specific and to use SQL Fiddle, so I have done so in hopes I can get this working properly.
Thanks in advance.
Is this what you need?
SQL Fiddle
SELECT *
from bankitem
where exists(
SELECT Name, ItemID, ID1, ID2, ID3
from item
where bankitem.Name = item.Name
and bankitem.ItemID = item.ItemID
and bankitem.ID1 = item.ID1
and bankitem.ID2 = item.ID2
and bankitem.ID3 = item.ID3
)
and name not in('RedPotion')
and charid <> 0

How do I query whether a row has N rows in another table that foreign key it?

Here is the general setup.
I have the tables Cards, Attributes, and a join table between them. (Let's call it Tags. It contains a CardID and an AttributeID.) The Attributes table is mostly just descriptions such as HasPower, IsPoisonous, ImmuneToWater, etc.
How would I go about querying for all cards that are both IsPoisonous and IsElectric? Let's assume I have the IDs for those already (13 and 45), so technically, the Attributes table does not need to be part of this SQL. I concocted something like this, but I'm not even sure if it is optimal.
SELECT *, (COUNT * FROM Tags t WHERE t.CardID = c.CardID AND t.AttributeID IN (13, 45)) AS TagCount
FROM Cards c
WHERE TagCount = 2
I hope my question makes sense. Basically, imagine you are looking at a web UI; you are sifting through a pool of ~5000 cards and want to filter down your results. So, you start checking boxes: "Poisonous", "Electric", "Immune to Water", etc. The results then filter down based on those attributes.
Thoughts?
SELECT *
FROM Cards
WHERE (Cards.Id IN (
SELECT DISTINCT CardID
FROM Tags
WHERE AttributeID IN (13, 45)
GROUP BY CardID
HAVING (COUNT(AttributeID) >= 2)
))
Inner query fetches the CardIDs that have at least two of the attributes you'd specified, then uses that result as a filter to fetch the actual card data in the outer query.
Although you could use multiple JOINs, I recommend you redesign your DB so that the attributes are simply columns in the Cards table.

Selecting multiple rows based on specific categories (mysql)

I don't think this is a duplicate posting because I've looked around and this seems a bit more specific than whats already been asked (but I could be wrong).
I have 4 tables and one of them is just a lookup table
SELECT exercises.id as exid, name, sets, reps, type, movement, categories.id
FROM exercises
INNER JOIN exercisecategory ON exercises.id = exerciseid
INNER JOIN categories ON categoryid = categories.id
INNER JOIN workoutcategory ON workoutid = workoutcategory.id
WHERE (workoutcategory.id = '$workouttypeid')
AND rand_id > UNIX_TIMESTAMP()
ORDER BY rand_id ASC LIMIT 6;
exercises table contains a list of exercise names, sets, reps, and an id
categories table contains an id, musclegroup, and type of movement
workoutcategory table contains an id, and a more specific motion (ie: upper body push, or upper body pull)
exercisecategory table is the lookup table that contains (and matches the id's) for exerciseid, categoryid, and workoutid
I've also added a column to the exercises table that generates a random number upon entering the row in the database. This number is then updated only for the specified category when it is called, and then sorted and displays the ascending order of the top 6 listings. This generates a nice random entry for me. (Found that solution elsewhere here on SO).
This works fine for generating 6 random exercises from a specific top level category. But I'd like to drill down further. Here's an example...
select all rows inside categoryid 4
then still within the category 4 results, find all that have movementid 2, and then find one entry with a typeid 1, then another for typeid 2, etc
TLDR; Basically there's a few levels of categories and I'm looking to select a few from here and a few from there and they're all within this top level. I'm thinking this could all be executed within more than one query but im not sure how... in the end I'm looking to end with one array of the randomized entries.
Sorry for the long read, its the best explanation I've got.
Just realized I never came back to this posting...
I ended up using several mysql queries within a switch based on what is needed during the request. Worked out perfectly.