Searching over related tables in Laravel - php

I'm trying to perform a LIKE-query with Laravel over several tables which are tied together by has_one-relationships: A Product has one Category and one Company. My LIKE-search should return a product if the query string matches product->name or if it matches product->category->name or if it matches product->company->name.
What would be an elegant way to achieve this?
products
| id | category_id | company_id | name |
| 1 | 1 | 1 | Television X345 |
| 2 | 2 | 1 | Radio Y234 |
companys
| id | name |
| 1 | Super Company |
| 2 | Hero Inc. |
categories
| id | name |
| 1 | Television |
| 2 | Radio |

Related

Split in comma-separated string and show in MySQL and PHP

I have a small database:
+-----------+-----------+------------------------+
| Name | Number | Hobby |
+-----------+-----------+------------------------+
| Alex | 2, 3 | Game, Shopping |
+-----------+------------------------------------+
It's mean Number 2 is Game and Number 3 is Shopping.
How can I show above data like this table
+-----------+-----------+
| 2 | Game |
+-----------+-----------+
| 3 | Shopping |
+-----------+------------
Your database is not normalized. You need a third table that will be what's usually called a join table.
The people table. The primary key is id
+-----------+-----------+
| Id | Name |
+-----------+-----------+
| 1 | Alex |
| 2 | Thor |
| 3 | Iron Man |
| 4 | Dr Stange |
| 5 | Thanos |
+-----------+------------
The hobbies Table
+-----------+-----------+
| Id | Name |
+-----------+-----------+
| 1 | Game |
| 2 | Shopping |
| 3 | Fighting |
+-----------+-----------+
Join table called (for example) people_hobbies
+-----------+-----------+
| person_id | hobby_id |
+-----------+-----------+
| 1 | 1 |
| 1 | 2 |
+-----------+-----------+
This people_hobbies table will use person_id and hobby_id to create a multi field primary key. This will ensure that you will not be able to add the same combination twice... which should not even make sense.
person_id is a foreign key that references the id from the people table.
hobby_id is a foreign key that references the id from the hobbies table.
Having foreign keys will let you avoid having a key in the people_hobbies table that do not exist in both the people and the hobbies table.
The example in the table below shows that the person id 1 has two hobbies (1 and 2). For a human, that translates to Alex's hobbies are Game and Shopping.
The above structure will let you manage your DB the way most people do.
Just keep a few things in mind:
You cannot add anything in people_hobbies before they exist in both people and hobbies tables
You must have the CASCADE UPDATE and CASCADE DELETE to the foreign key definitions so that when you delete a person or a hobby from your tables, it will remove the relationship from the people_hobbies table.
SELECT * FROM ints;
+---+
| i |
+---+
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
+---+
SELECT * FROM bad_schema;
+------+--------+----------------+
| name | number | hobby |
+------+--------+----------------+
| Alex | 2, 3 | Game, Shopping |
+------+--------+----------------+
CREATE TABLE better_schema AS
SELECT DISTINCT name
, SUBSTRING_INDEX(SUBSTRING_INDEX(number,',',i+1),',',-1) + 0 number
, TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(hobby,',',i+1),',',-1)) hobby
FROM bad_schema
, ints;
SELECT * FROM better_schema;
+------+--------+----------+
| name | number | hobby |
+------+--------+----------+
| Alex | 2 | Game |
| Alex | 3 | Shopping |
+------+--------+----------+

Doctrine orm one to many with reference key also containing strings

I have an entity called books and another one users.
Each book can have many authors(users).
So when I add a book I select the users that are registered on the site.
But if the author of the book doesn't have an account on the site I want to type his name by hand.
+----+---------+-----------+--+
| id | book_id | author_id | |
+----+---------+-----------+--+
| 1 | 1 | 1 | |
| 2 | 1 | Mr.Paul | |
+----+---------+-----------+--+
See how the author_id is a string but also an reference key to an user?
Can I do this with doctrine or I will have to manage the inserts myself?
Edit:I have no idea what the right title should be
Edit2:A possible solution will be to make another table containing only authors that don't have an account on the website.
I would recommend following approach
You have a table books a table accounts and the following:
authors_books
+----+---------+-----------+--+
| id | book_id | author_id | |
+----+---------+-----------+--+
| 1 | 1 | 1 | |
| 2 | 1 | 2 | |
+----+---------+-----------+--+
authors
+----+---------+------------+--+
| id | name | account_id | |
+----+---------+------------+--+
| 1 | Mr. Paul | 1 | |
| 2 | Simon | (empty) | |
+----+---------+-------------+--+
the account_id can be empty

Sql Select data pick id from string

Category Table
+----+-----------------------+
| id | category_name |
+----+-----------------------+
| 1 | Buy Book |
| 2 | Buy other thinks |
+----+-----------------------+
Buy Table
+----+-----------------------+----------+-------------+----------+--------+-------+
| id | identity | name | description | per_rate | bought | costs |
+----+-----------------------+----------+-------------+----------+--------+-------+
| 1 | PROJECT[1]CATEGORY[1] | BOOK | PHP BOOK | 10 | 50 | 5000 |
| 2 | PROJECT[1]CATEGORY[1] | BOOK | PHP BOOK | 10 | 40 | 4000 |
| 3 | PROJECT[2]CATEGORY[1] | BOOK | JS BOOK | 2 | 50 | 100 |
+----+-----------------------+----------+-------------+----------+--------+-------+
I Want to Select category name from Other table when I select this table.
identity: PROJECT[project_id]CATEGORY[category_id]
So There are any way to pick the category id and select category name from other table
I Want Like This Table
+----+---------------+-----------------------+----------+-------------+----------+--------+-------+
| id | category_name | identity | name | description | per_rate | bought | costs |
+----+---------------+-----------------------+----------+-------------+----------+--------+-------+
| 1 | Buy Book | PROJECT[1]CATEGORY[1] | BOOK | PHP BOOK | 10 | 50 | 5000 |
| 2 | Buy Book | PROJECT[1]CATEGORY[1] | BOOK | PHP BOOK | 10 | 40 | 4000 |
| 3 | Buy Book | PROJECT[2]CATEGORY[1] | BOOK | JS BOOK | 2 | 50 | 100 |
+----+---------------+-----------------------+----------+-------------+----------+--------+-------+
You have a really bad data structure. The project and category should be in their own columns, with numbers stored properly as numbers, and proper foreign key relationships. In MySQL, doing this might require a trigger, but it is worth it.
Sometimes, we are stuck with other people's bad decisions. You can do what you want using like:
select b.*, c.category_name
from buy b join
category c
on b.identity like concat('%CATEGORY[', c.id, ']');
However, you should probably put effort into fixing the broken data structure.

Junction tables in MySQL

(Sorry, my english isn't very good)
Hi, I am trying to learn how to work with junction tables in MySQL and I can't figure how to do something. I know the basics of MySQL but I have never worked with "JOIN".
In this test project, I would like to be able to show on a page the app of a given category (you click on "Games", only the apps that are in the "Games" category will be displayed on the page). I would like to know what the SQL request should look like.
Second question, let's say that an App could fit 2 different categories, how can I manage to give that app 2 different Category_ID in my database ?
Here is what my Database looks like at the moment :
Table name: APPS
+------------+-------------------+
| App_ID (pk)| App_Name |
+------------+-------------------+
| 1 | Weather Network |
| 2 | Is it sunny 2.0 |
| 3 | The Weather App |
| 4 | Zelda |
| 5 | Megaman |
| 6 | Doom 3 |
+------------+-------------------+
Table name : CATEGORY
+-----------------+-----------------+
| Category_ID (pk)| Category_Name |
+-----------------+-----------------+
| 1 | Games |
| 2 | Weather |
+-----------------+-----------------+
Table name : JUNCTION_APP_CATEGORY
+----------------+--------------------+
| APP_ID (pk) | Category_ID (pk) |
+----------------+--------------------+
| 1 | 2 |
| 2 | 2 |
| 3 | 2 |
| 4 | 1 |
| 5 | 1 |
| 6 | 1 |
+----------------+--------------------+
For your first question, the answer is
SELECT a.*, c.*
FROM APPS a, CATEGORY c, JUNCTION_APP_CATEGORY ac
WHERE a.App_ID=ac.APP_ID
AND c.Category_ID=ac.Category_ID
AND ac.Category_ID=<category_id for category "Games">
For your second question, you can use both APP_ID and Categor_ID as the primary key of table JUNCTION_APP_CATEGORY(note NOT TWO pks, but use the two columns together as ONE pk). So that you can put data like this:
+----------------+--------------------+
| APP_ID (pk) | Category_ID (pk) |
+----------------+--------------------+
| 1 | 1 | <-- APP_ID=1 belongs to both cat 1 & 2
| 1 | 2 |
| 2 | 2 |
| 3 | 2 |
| 4 | 1 |
| 5 | 1 |
| 6 | 1 |
+----------------+--------------------+

In a single mysql query, select multiple rows from one table, each containing multiple rows from a linking table

Have two tables with a linking table between them.
USERS
+-------+---------+
| userID| Username|
+-------+---------+
| 1 | Nate |
| 2 | Nic |
| 3 | John |
+-------+---------+
SITES
+--------+---------+
| siteID | Site |
+--------+---------+
| 1 | art |
| 2 | com |
| 3 | web |
+--------+---------+
USER_SITES
+-------------+---------+---------+
| user_site_id| user_id | site_id |
+-------------+---------+---------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 2 | 2 |
| 5 | 2 | 3 |
+-------------+---------+---------+
I want to do one query that will output like this
USERS
+---------+----------------+
| username| sites |
+---------+----------------+
| Nate | art, com, web |
| Nic | com, web |
+---------+----------------+
Can that be done easily with one query?
I would like to be able to do that in MySQL, and POSTgreSQL - but I'll take whatever I can get!
It can be done in MySQL using GROUP_CONCAT:
SELECT
username,
GROUP_CONCAT(Site ORDER BY Site SEPARATOR ', ') AS sites
FROM USER_SITES
JOIN USERS ON USER_SITES.user_id = USERS.userID
JOIN SITES ON USER_SITES.site_id = SITES.siteID
GROUP BY username
Result:
+---------------------------+
| username | sites |
+---------------------------+
| Nate | art, com, web |
| Nic | com, web |
+---------------------------+
To see how to emulate GROUP_CONCAT in PostgreSQL see this question:
Postgresql GROUP_CONCAT equivalent?

Categories