MySQL - How to ORDER BY RELEVANCE? INNODB Table - mysql

I've got about 20,000 rows in an INNODB table called 'cards', so FULLTEXT is not an option.
Please consider this table:
id | name | description
----------------------------------------------------------
1 John Smith Just some dude
2 Ted Johnson Another dude
3 Johnathan Todd This guy too
4 Susan Smith Her too
5 Sam John Bond And him
6 John Smith Same guy as num 1, another record
7 John Adams Last guy, promise
So, say the user searches for 'John', I want the result set to be in the order of:
7 John Adams
6 John Smith
3 Johnathan Todd
5 Sam John Bond
2 Ted Johnson
Please note that we've only pulled 'John Smith' once, we took his most recent entry. Due to my data, all names are for the same exact person, no need to worry about 2 different guys named John Smith.
Ideas? Let me know if I can clarify anything.

version 1:
SELECT max(id) id, name
FROM cards
WHERE name like '%John%'
GROUP BY name
ORDER BY CASE WHEN name like 'John %' THEN 0
WHEN name like 'John%' THEN 1
WHEN name like '% John%' THEN 2
ELSE 3
END, name
version 2:
SELECT max(id) id, name
FROM cards
WHERE name like '%John%'
GROUP BY name
ORDER BY CASE WHEN name like 'John%' THEN 0
WHEN name like '% %John% %' THEN 1
WHEN name like '%John' THEN 2
ELSE 3
END, name

Related

How to merge data from table database in application level not database level?

I am stuck to merge data from my application.
Let's say I have:
PetBooks Table:
id
book_name
Pet:
id
book_id
code
name
type
Petbooks
1 MyPet
2 MyPet(Copy)
Pet:
1 1 CAT1 Josh Cat
2 1 CAT2 Ron Cat
3 1 DOG1 Max Dog
4 2 CAT1 Josh Cat
5 2 CAT2 Ronnie Cat
6 2 DOG1 Max Dog
Question: I want to merge Book id 1 and book id 2, it's should check the pet code, if the pet code is the same, then it should assume it's the same, but it should check the name, and type. If there is different, then it should use comma (,) to join.
So the result should look like this:
Merge book id 1 to book id 2:
Petbooks
2 MyPet(Copy)
Pet:
4 2 CAT1 Josh Cat
5 2 CAT2 Ronnie,Ron Cat
6 2 DOG1 Max Dog
Look at pet id 5, the name is different so it will concat the pet name with a comma
The solution I think is to get all the pet where book_id = 1, and get all the pet where book_id = 2, and check it one by one and insert it one by one, but it's so slow, I think it's n^2, and it's very slow especially when the data grow

MySQL Query using data from two tables

I have two tables like so:
Table 1: tracks
id | artist | track
---------------------------------------
1 Tom Smith This Time is Right Time
2 Tom Smith Oh Yes
3 John Doe Every Time I See You
Table 2: festival_bands
id | fest_title | fest_artist
---------------------------------------
1 Hoe Down Fest 2019 John Doe
2 Copperland Fest Tom Smith
3 Copperland Fest Reggie Wisk
4 Copperland Fest Tom Smith
5 Copperland Fest John Doe
6 Bluegrass Memories John Doe
I need to show only ONE "track" from table 1 for each festival listing from Table 2 like so:
Results:
Copperland Festival:
-----------------------
Tom Smith This Time is Right Time
John Doe Every Time I See You
In layman's terms, the logic would be along the lines of:
Get only one track from TABLE 1 where artist equals (or matches) fest_artist from TABLE 2
I referenced a similar question which advised something in the direction of:
$sql="select * from tracks WHERE (artist) in (select fest_artist from festival_bands group by name)" but with no luck.
You can use a correlated subquery to get a random track for the artist:
select fb.*,
(select t.track
from tracks t
where t.artist = fb.fest_artist
order by t.counter desc
) as most_popular_track
from festival_bands fb;

SQL Database Design | Roles relationship between managers and group

I need some help to design correctly a SQL database. Here is what I want :
**Group A :**
- Alice (Manager)
- Bob
- Carol
**Group B :**
- Dave (Manager)
- Eve
- Mallory
**Group C :**
- Oscar (Manager)
- Trudy
- Isaac
**Group Z**
- Admin (Manager)
- Alice
- Dave
- Oscar
A few restrictions :
1) Each member can see the planning of the people in their group. For
example when Bob logs in, he can consults Alice and Carole planning
added to his own.
2) Manager can update the timetable for the people in their group but not their own! So
Alice can manage Bob and Carol, Dave can manage Eve and Mallory, Oscar
manages Trudy and Isaac and finally Admin manages Alice, Dave and
Oscar planning.
3) It has been agreed that Alice would help Dave to manage his group,
so Alice can manage Eve and Mallory (but not Dave), but Eve and
Mallory can't see Alice's planning as she still belongs to group A.
4) Admin is the only manager that can update his own planning. Also he
can consults everyone planning but only people in their group can see
his planning (So Alice, Dave and Oscar basically)
5) User can be in multiple group (look at Alice, Dave and Oscar that
are also in group Z). They will have the choice to consult the
planning of a specified group when they will log in so it is not an issue.
I would have done something like :
TABLE User
id
nom
prenom
login
password
userGroup
TABLE group
id
groupName
groupManager
But this will obviously not work unless I could set an Array as a value for groupManager (I'm not good at SQL, but I am pretty sure it's impossible, isn't it?)
Could someone guide me to something that would allow me to reach what I expect ?
Since your design requires a many-to-many relationship between users and groups (a group contains multiple users; a user can be in multiple groups), I would use something like this:
User
(
ID
, Name
, Login
, Password
, etc.
)
Group
(
ID
, Name
, etc.
)
Group_Role
(
ID
, Role_Description
, etc.
)
User_Group_Role
(
ID
, User_ID -- foreign key to User.ID
, Group_ID -- foreign key to Group.ID
, Group_Role_ID -- foreign key to Group_Role.ID
)
So your Users table will contain
1 | Alice
2 | Bob
3 | Carol
4 | Dave
5 | Eve
6 | Mallory
99 | Admin
, your Groups table will contain
1 | Group A
2 | Group B
99 | Group Z
, your Group_Roles table will contain things like
1 | Consult
2 | Manage -- cannot manage self
3 | Assist
4 | SuperManage -- can manage self
, and finally, the User_Group_Role table:
1 | 1 | 1 | 2 -- Alice manages Group A
2 | 2 | 1 | 1 -- Bob consults in Group A
3 | 3 | 1 | 1 -- Carol consults in Group A
4 | 4 | 2 | 2 -- Dave manages Group B
5 | 1 | 2 | 3 -- Carol assists with Group B
6 | 5 | 2 | 1 -- Eve consults in Group A
7 | 6 | 2 | 1 -- Mallory consults in Group A
etc.
Does that make sense?

Group by X or Y?

I'm trying to figure out how to GROUP BY on multiple columns. I want to group items when the SSN or the address matches. For example, here are three records:
account_number | name | ssn | address
---------------+--------------+-------------+----------------------
23952352340 | SMITH INC | 123-45-6789 | P.O. BOX 123
3459450340 | JOHN SMITH | 123-45-6789 | 123 EVERGREEN TERRACE
45949459494 | JANE SMITH | 395-23-1924 | 123 EVERGREEN TERRACE
And here's what I'd like to end up with:
names
----------------------
SMITH INC, JOHN SMITH, JANE SMITH
Any suggestions?
You can't do this easily in MySQL.
The problem is that the relation "is similar to" as you define it is not transitive. In your example, Smith Inc is similar to John Smith (per SSN) and John Smith is similar to Jane Smith (per name), but Smith Inc is not similar to Jane Smith. So there is no single value that all records could be compared with and GROUP BY won't help here.
In other systems which support recursion you could build a transitive closure of this relation which would allow grouping, but this is not an easy task in MySQL.
Like this:
SELECT
name,
ssn,
COUNT(*)
FROM TheTable
GROUP BY
name,
ssn

MySQL - Search and replace table1.field's contents with contents of table2.otherfield

I need a MySQL query that will do the following:
Instead of the alpha team names in the 3rd column of the players table, I want it to reference teams.id
table: players
id player_name team
------------------------------------------
1 Sue Smith Silly Chimps
2 Mike Olson Black Cats
3 Tim Hood Silly Chimps
4 Chris Row Grease Monkeys
5 Fred Ware Black Cats
table: teams
id name
-------------------------------
1 Black Cats
2 Grease Monkeys
3 Silly Chimps
So after the Search and Replace update, the players table will look like:
id player_name team
------------------------------------------
1 Sue Smith 3
2 Mike Olson 1
3 Tim Hood 3
4 Chris Row 2
5 Fred Ware 1
The teams table will remain untouched. Let me know if I can clarify anything.
update players, teams set players.team = teams.id where players.team = teams.name