mysql primary key starts with pattern - mysql

I have 2 tables books, mobiles in a Mysql database.
Tables structure being,
1. book_id|book_name
2. mobile_id|mobile_name
A third table products with the following structure is also created,
product_id|product_name
Now, I want the book_id to start with a pattern in mysql.
For example,
book_ids -> 11,12,13,14,15,16,17,18,19,110,111,112,...
mobile_ids -> 21,22,23,24,25,26,27,28,29,210,211,212,...
Now, in my products table I can have,
product_id -> 11,21,16,26, if this starts with pattern is not set,
then the problem would be,
product_id -> 1,1,6,6..its not unique.
How to handle this..?
Edited stuff below:
So, are you meaning this..?
category_table
category_id | category_name
1 | books
2 | mobiles
book_table
book_id | book_name
1 | da vinci code
2 | alchemist
mobile_table
mobile_id | mobile_name
1 | nokia
2 | samsung
product_table
id | product_name | product_id | category_id
1 | da vinci code | 1 | 1
2 | alchemist | 2 | 1
3 | nokia | 1 | 2
4 | samsuing | 2 | 2

You seem to be duplicating information without a reason.
Just create a products table with:
id | name | type (e.g. 0 book, 1 mobile, etc) | price | ....

Related

mysql query for getting a list of items with reference to another table

i have table like this
+----+-------+-------------+
| id | items | name |
+----+-------+-------------+
| 1 | 1,2,3 | hot deals |
| 2 | 2,3,4 | offers |
+----+-------+-------------+
where items are the id of product
here is the product table (mini version)
+-----------+--------------------+
| productid | productname |
+-----------+--------------------+
| 1 | sony mobile |
| 2 | iphone 4s |
| 3 | dell laptop v1 |
| 4 | samsung mouse |
+-----------+--------------------+
i need to get result as array of items with name
ex
[hot deals =>[(1,sony mobile),(2,iphone 4s),(3,dell laptop v1 )
],offers=>[--]]
can achieve this in (MYSQL)stored procedure if not how can i achieve this with minimum numberof queries
side note:first table will have maximum of 6 rows
You can use a join with find_in_set():
select t.id, t.name, p.productname
from yourtable t
join products p on find_in_set(p.productid, t.items)
SQL Fiddle Demo
As a side note, I'd recommend looking into database normalization. Better to create another 1-n table to store the comma separated values separately.

Is it possible to normalize the table so that it can contain one Value in one row?

I have a table containing three column BusNo, BusRoute & BusStop where BusStop column contain multiple comma separated values. I want to normalize it so that the table contain one stop in one Row. Ex.
BusNo BusRoute BusStop
1 Rajendra Nagar to Noida Apsara,Shahadara,Shakarpur,Mother Dairy
I want to make the stops in multiple row would it be good approach I have more that 1000 BusNo here.
My suggestion would be to have two new tables: BusStops and BusRouteBusStops.
BusStops will have one line for each bus stop, containing at least two columns: StopNumber and StopName.
BusRouteBusStops will be the table that links the BusRoute table with the BusStops table. Each line in this table will have a primary key from BusRoutes and from BusStops.
The idea is to keep the bus stops in a table, regardless of if and where they are used. That way you can use a single stop in however many routes you want. Also, if you decide to remove a stop from all the routes, it is still kept and is available for use for new routes.
If you want to represent the order of the bus stops in the route, it can be added as a column to the BusRouteBusStops table.
Tables example:
Table BusRoutes - primary-Key(BusNo)
===============
BusNo | BusRoute
1 | Rajendra Nagar to Noida
Table BusStops - primary-Key(StopNumber)
===============
StopNumber | StopName
1 | Apsara
2 | Shahadara
3 | Shakarpur
4 | Other Stop
5 | Mother Dairy
Table BusRouteBusStops - primary-Key(BusNo+StopNumber)
===============
BusNo | StopNumber | stpoOrder
1 | 1 | 1
1 | 2 | 2
1 | 3 | 3
1 | 5 | 4
A query to get all the bus numbers that go through a given stop (say: Apsara), using MySql syntax, will be:
SELECT BR.*
FROM BusRoutes BR, BusStops BS, BusRouteBusStops BRBS
WHERE BR.BusNo=BRBS.BusNo
AND BS.StopNumber=BRBS.StopNumber
AND BS.StopName="Apsara"
To resolve a m:n relation, you normally use an additional table. As you have everything in one table right now, that means two additional tables for you.
Table structure
bus_stop: id, name
bus_route: id, description
stop_to_route_relation: bus_route, bus_stop
Example
bus_stop
--------------------
| id | name |
--------------------
| 1 | CityA |
--------------------
| 2 | CityB |
--------------------
| 3 | CityC |
--------------------
bus_route
-----------------------------
| id | bus_no | description |
-----------------------------
| 1 | 5 | CityA to B |
-----------------------------
| 2 | 5 | CityA to C |
-----------------------------
stop_to_route_relation
------------------------
| bus_route | bus_stop |
------------------------
| 1 | 1 |
------------------------
| 1 | 2 |
------------------------
| 2 | 1 |
------------------------
| 2 | 3 |
------------------------
Example query
select
br.bus_no,
bs.name
from
bus_route br
left join stop_to_route_relation str on (br.id = str.bus_route)
left join bus_stop bs on (str.bus_stop = bs.id);
If you want to normalize BusStop field then you need to make a new table for it. Like this:
Table: Bus
===================================
| BusNo | BusRoute
===================================
| 1 | Rajendra Nagar to Noida
===================================
Table: BusStop
--------------------------
| BusNo | BusStop
--------------------------
| 1 | Apsara
--------------------------
| 1 | Shahadara
--------------------------
| 1 | Shakarpur
--------------------------
| 1 | Mother Dairy
--------------------------
In the BusStop table the BusNo is the Foreign Key that links it to Bus table.
You mentioned that you have 1000 BusNo so I guess it will require a lot of resources since normalizing it will need more rows for saving the BusStop for each BusNo. For instance, each BusNo has 5 BusStops then your new table for BusStop will approximately have 1000 x 5 rows (Your saving every BusStop of Bus in the table). The advantage that I see here is you can do more queries in normalizing it. You weigh the pros and cons in deciding. Goodluck.

Link to multiple foreign rows from one row

I really don't know how this is called so I couldn't find an answer.
For example I have the following tables:
Table products Table users
+----------+----------+----------+ +----------+----------+
| id | name | price | | username | products |
+----------+----------+----------+ +----------+----------+
| 1 | Bread | 1.5 | | James | 1, 2 |
+----------+----------+----------+ +----------+----------+
| 2 | Cookies | 2.0 | | David | 2, 3 |
+----------+----------+----------+ +----------+----------+
| 3 | Milk | 1.2 | | Paul | 3, 1 |
+----------+----------+----------+ +----------+----------+
products.id is the foreign key for users.products.
I would like to get the name and price of all David's products using a MySQL query. This should return the following:
+----------+----------+
| name | price |
+----------+----------+
| Cookies | 2.0 |
+----------+----------+
| Milk | 1.2 |
+----------+----------+
The JOIN function would be the best to use I guess, but David can have just 1 or 100 products. Creating 100 columns to fit all products doesn't sound very efficient.
How can I realize this?
Currently I'm just fetching everything and filter it using PHP, this is not a problem at the moment but as the tables will grow I guess this will be very inefficient.
This could be solved by changing your data model.
users
+----------+----------+
| id | username |
+----------+----------+
| 1 | Fred |
+----------+----------+
| 2 | John |
+----------+----------+
products
+----------+----------+----------+
| id | name | price |
+----------+----------+----------+
| 1 | Bread | 1.5 |
+----------+----------+----------+
| 2 | Cookies | 2.0 |
+----------+----------+----------+
| 3 | Milk | 1.2 |
+----------+----------+----------+
And here comes the magic: You could connect the two tables using a third table:
user_procuct_connections
+----------+----------+------------+
| id | user_id | product_id |
+----------+----------+------------+
| 1 | 1 | 2 | -> Fred has Cookies
+----------+----------+------------+
| 2 | 1 | 3 | -> Fred also has Milk
+----------+----------+------------+
| 3 | 2 | 1 | -> John has Bread
+----------+----------+------------+
If you want a user to be able to own a single product only, then you can remove the id column, an make the user_id and product_id primary key together.
Then when you want to get for example all of Freds products then just
SELECT
*
FROM
products
WHERE
id IN (
SELECT
product_id
FROM
user_procuct_connections
WHERE
user_id = 1
)
You could try this:
SELECT * FROM products pt
where FIND_IN_SET(pt.id,(select us.prices from users us
WHERE us.username = "David"));
Working fiddle: http://sqlfiddle.com/#!2/4f78d/2
The design for the 'Users' table is wrong. Instead of working around this bad design, please change the design.
So effectively, you design could be as such:
Table Products :
ID Name Price
1 Bread 1.5
2 Cookies 2.0
3 Milk 1.2
Table users :
Username Products
James 1
James 2
David 2
David 3
Paul 3
Paul 1
You see, you can have multiple rows for each user i.e.one row for each product in the Users table. You can maintain another Boolean field to identify which ones are currently 'active' or 'applicable'. Joins' would be much easier in that case. Also, updating records would also be easier. In case, in future you'd want to retrieve & analyse data from historic records, that would be possible too!!!
Another thing with the current design is that times and again you'd have to work around the infamous "comma-seperated values". Let's say you have a record as such:
Username Products
James 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
If you need to sort this data into rows, you'd have to work-around the 'Comma-seperated' values so many times. Imagine doing that for 'n' number of records!!
Hope this helps!!!
If you join the tables like:
SELECT name, price FROM products AS p INNER JOIN user_products AS up ON up.id = p.product_id AND up.user_id = <davids id>
You will get an array where first column will be the name and the second the price. You can then do what you want with it in PHP and change the array. You don't have to filter anymore.

Application specific MySQL table Structure

I have a question about my DB table structure. I want to know if i'm on the right track or if I have missed a good alternative. Here is the case:
To make it easy to read, I haven't pasted the full contents as my question is only about the structure.
2 tables:
1: id (AI), task
2: id, name, task
Table 1 presents dynamic check-boxes which can be altered by an admin panel so the contents would be like this
1 task1
2 task2
5 task5
(3 & 4 are missing cause the administrator deleted those records).
In table number two are the people who should do the tasks from table 1. And the goal is that the tasks wich are not checked will be displayed.
So the contents of table 2 would be:
1 Name1 1,5
2 Name2 1,2
3 Name3 1,2,5
The numbers in table 2 represent the checked boxes from table 1. So with a query i can compare the numbers from table 2 with the id's from table 1 and display the missing ids as "todo".
In my opinion this looks very overdone, and there must be an easier way to create dynamic options which can be compared and stored as a todo.
Suggestions are welcome!
I suggest you to use basic structure for many-to-many relationship:
tasks users user_tasks
+----+-----------+ +----+-------+ +---------+---------+
| id | name | | id | name | | user_id | task_id |
+----+-----------+ +----+-------+ +---------+---------+
| 1 | Buy milk | | 1 | John | | 1 | 2 |
| 2 | Get drunk | | 2 | Tim | | 3 | 2 |
| 3 | Have fun | | 3 | Steve | | 2 | 4 |
| 4 | Go home | +----+-------+ | 3 | 4 |
+----+-----------+ +---------+---------+
And you can fetch unassigned tasks using following query:
SELECT
tasks.*
FROM
tasks
LEFT JOIN
user_tasks
ON (tasks.id = user_tasks.task_id)
WHERE
user_tasks.user_id IS NULL
You also can fetch users who have no assigned tasks:
SELECT
users.*
FROM
users
LEFT JOIN
user_tasks
ON (users.id = user_tasks.user_id)
WHERE
user_tasks.user_id IS NULL
Hope this will help you.

Special unique columns

I have a situation where a website (a source) has multiple feeds (category separated)
Feed Table
feed_id | source_id | feed_url
1 | 1 | http://example.com/rss?category=1
2 | 1 | http://example.com/rss?category=5
3 | 2 | http://textample.com/rss
Item Table
item_id | true_id | feed_id
1 | 1332 | 1
2 | 76549 | 1
3 | 76549 | 2
4 | 76549 | 3
the true id is the id I try to get from the source site.
I want the item id 2 & 3 are the same, because they share the same source (example.com), item 4 is not the same because it has a different source (textample.com)
Is there a way I can enforce that consistency, without adding the source id to the Item Table?
RUN
ALTER TABLE `itemTable` ADD UNIQUE (`feed_id`);