What would be the most efficient way of creating my MySQL database - mysql

I'm thinking of doing something like...
Table Pants (20 entrees)
| ID | Item | Description | Price
Table Shirts (20 entrees)
| ID | Item | Description | Price
Table Socks (5 entrees)
| ID | Item | Description | Price
Then I run a php foreach ID in $table, to populate the list on a page.
So would this be an efficient way of doing this since some of my tables might not have many entrees? Or should I have all the entrees in one table and add an extra field for the different categories and find another way of populating my page via the new field? Or maybe a greater idea?
Thanks for your time.

your model is not flexible and not efficient. Your second solution is the good one create a table named items and add an extra field named categories which should be a foreign key.
you can check this http://sqlfiddle.com/#!2/74c91/1, here is all you need
here is the code needed for the database creation :
/*!40101 SET #OLD_CHARACTER_SET_CLIENT=##CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET FOREIGN_KEY_CHECKS=0 */;
-- Dumping structure for table database.categories
CREATE TABLE IF NOT EXISTS `categories` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`created` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- Dumping data for table database.categories: ~0 rows (approximately)
/*!40000 ALTER TABLE `categories` DISABLE KEYS */;
INSERT INTO `categories` (`id`, `name`, `created`) VALUES
(1, 'Pants ', '2012-12-15 11:37:27'),
(2, 'Shirts ', '2012-12-15 11:37:36'),
(3, 'Socks ', '2012-12-15 10:38:47');
/*!40000 ALTER TABLE `categories` ENABLE KEYS */;
-- Dumping structure for table database.clothes
CREATE TABLE IF NOT EXISTS `clothes` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`item` varchar(255) NOT NULL,
`description` text,
`category_id` int(10) NOT NULL,
`created` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `category_id` (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- Dumping data for table database.clothes: ~0 rows (approximately)
/*!40000 ALTER TABLE `clothes` DISABLE KEYS */;
INSERT INTO `clothes` (`id`, `item`, `description`, `category_id`, `created`) VALUES
(1, 'red socks', 'Red Socks Rocks', 3, '2012-12-15 10:39:06'),
(2, 'blue socks', 'nice socks too', 3, '2012-12-15 10:39:18'),
(3, 'grey pants', 'pretty cool', 1, '2012-12-15 10:40:34'),
(4, 'Blue Shirt', 'Nice blue shirt', 2, '2012-12-15 10:40:10');
/*!40000 ALTER TABLE `clothes` ENABLE KEYS */;
/*!40014 SET FOREIGN_KEY_CHECKS=1 */;
/*!40101 SET CHARACTER_SET_CLIENT=#OLD_CHARACTER_SET_CLIENT */;
And here is the code to retrieve your data:
SELECT
clothes.id AS clotheId,
clothes.item AS clotheItem,
clothes.description AS clotheDescription,
categories.id AS categoryId,
categories.name AS categoryName
FROM clothes
LEFT JOIN categories
ON clothes.category_id=categories.id;

I'd go with the latter.
ID | Item | Description | Price | Type
Then use a query like:
SELECT * FROM items WHERE type='$type'

I would not store this data in separate tables. Create one table, then include an indicator as to the type of item it is.
Similar to this:
create table ClothingItems
(
id,
typeid,
item,
description,
price
);
create table clothingType
(
typeid,
name
);
Then to query you can use:
select *
from clothingitems i
left join clothingType t
on t.typeid = t.typeid
where t.name = 'socks'

Well, it might not have so many entrees for the moment. But maybe in the future? Don't put yourself in a corner :).
Ask yourself the question; -Can an article belong to more than one category?
If NO, you should create at least 2 tables (one-to-many relation):
categories
id|title|description|...
articles
id|category_id|title|price|...
If YES, you should create at least 3 tables (many-to-many relation):
categories
id|title|description|...
articles
id|category_id|title|price|...
articles_categories
article_id|category_id
Best of luck :)

Related

Can I run a SELECT query that depends on two rows from a table without using subqueries

Suppose the schemas are
users(id, name)
users_attributes(user_id, attribute_name, attribute_value)
Sample data:
--
-- Database: `sample_db`
--
CREATE DATABASE IF NOT EXISTS `sample_db` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
USE `sample_db`;
-- --------------------------------------------------------
--
-- Table structure for table `users`
--
CREATE TABLE `users` (
`id` int(11) NOT NULL,
`name` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Dumping data for table `users`
--
INSERT INTO `users` (`id`, `name`) VALUES
(1, 'Tim'),
(2, 'Joe'),
(3, 'Bob');
-- --------------------------------------------------------
--
-- Table structure for table `users_attributes`
--
CREATE TABLE `users_attributes` (
`user_id` int(11) NOT NULL,
`attribute_name` varchar(50) NOT NULL,
`attribute_value` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Dumping data for table `users_attributes`
--
INSERT INTO `users_attributes` (`user_id`, `attribute_name`, `attribute_value`) VALUES
(1, 'height', '10'),
(1, 'over_18', 'yes'),
(2, 'height', '5'),
(3, 'height', '7');
--
-- Indexes for dumped tables
--
--
-- Indexes for table `users`
--
ALTER TABLE `users`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `users_attributes`
--
ALTER TABLE `users_attributes`
ADD UNIQUE KEY `user_id` (`user_id`,`attribute_name`,`attribute_value`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `users`
--
ALTER TABLE `users`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
COMMIT;
Right now I'm calling INNER JOIN on a specific attribute_name so my selection also returns that along with the user id and name. Now I want to exclude from whatever I selected, if they contain a certain other attribute. I know I can accomplish that by using a NOT IN (SELECT ...) conditional but can I do that without having to select again?
EDIT:
Attributes may or may not exist for all users. For example, I would like to fetch id, name, attribute_value where attribute_name = height but only if attribute_name over_18 does not exist or is 'no'

One column in a table referring to another column where there are duplicate data in SQL

I want to build simple database system about bike (or bicycle) rental store.
Here are the tables, and columns in parantheses:
Model (MNr, Modelname, dayprice)
Bike (MNr, CopyNr, Frame, Color)
Customer (CNr, Name, Surename, MobileNr)
Rental (CNr, MNr, CopyNr, DateOut, DateIn)
(MNr stands for model number, CNr stands for customer number).
Models are bike models, Bike table shows data on each particular bike.
There can be several bikes of each model, to distinguish between them
"CopyNr" column is used, where each bike in a given model is numbered 1, 2, 3, etc.
Rental: A rental relationship always applies to only one bike and one customer.
So I put the following primary and foreign keys:
Model (MNr (PK), Modelname, dayprice)
Bike (MNr (FK), CopyNr (PK), Frame, Color)
Customer (CNr (PK), Firstame, Surname, MobileNr)
Rent (CNr (FK), MNr (FK), CopyNr (FK), DateOut, DateIn)
The "CopyNr" at "Rental" is referring to the "CopyNr" of "Bikes". So I used "CopyNr" as
primary key column.
But that column can contain duplicate values, like there can be copy nr 2 of model A and copy nr 2 of
model B.
And primary key columns don't allow duplicate values.
I wrote the following in the SQL file, and when but it on PHPMyAdmin.
Here's the code from SQL code:
[It had Norwegian names, I changed it to English, thus color names are Norwegian]
-- phpMyAdmin SQL Dump
-- version 4.8.4
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1:3306
-- Generation Time: Feb 04, 2020 at 07:15 PM
-- Server version: 10.2.26-MariaDB-log
-- PHP Version: 7.1.30
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+01:00";
/*!40101 SET #OLD_CHARACTER_SET_CLIENT=##CHARACTER_SET_CLIENT */;
/*!40101 SET #OLD_CHARACTER_SET_RESULTS=##CHARACTER_SET_RESULTS */;
/*!40101 SET #OLD_COLLATION_CONNECTION=##COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
--
--
-- --------------------------------------------------------
--
-- Table structure for table `Customer`
--
CREATE TABLE `Customer` (
`CNr` int(2) NOT NULL,
`Firstname` varchar(20),
`Surname` varchar(20),
`MobileNr` varchar(8),
PRIMARY KEY (CNr)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `Customer` (`CNr`, `Firstname`, `Surname`, `MobileNr`) VALUES
(1, 'Olav', 'Petterses', '88888888'),
(2, 'Petter', 'Olavsson', '44444444');
-- --------------------------------------------------------
--
-- Table structure for table `Model`
--
CREATE TABLE `Model` (
`MNr` int(5) NOT NULL,
`Modelname` varchar(20),
`Dayprice` double DEFAULT NULL,
PRIMARY KEY (MNr)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `Model` (`MNr`, `Modelname`, `Dayprice`) VALUES
(2, 'FirstPrice', 10),
(15, 'DBS', 50),
(16, 'DBS', 60);
-- --------------------------------------------------------
--
-- Table structure for table `Bike`
--
CREATE TABLE `Bike` (
`MNr` int(5),
`CopyNr` int(2) NOT NULL,
`Frame` int(3),
`Color` varchar(10),
PRIMARY KEY (`CopyNr`, `MNr`),
CONSTRAINT `Bike_ibfk_1` FOREIGN KEY (`MNr`) REFERENCES `Model` (`MNr`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `Bike` (`MNr`, `CopyNr`, `Frame`, `Color`) VALUES
(2, 1, 55, 'rød'),
(15, 1, 65, 'rød'),
(16, 1, 55, 'grønn'),
(2, 2, 55, 'rød'),
(15, 2, 65, 'grønn');
-- --------------------------------------------------------
--
-- Table structure for table `Rent`
--
CREATE TABLE `Rent` (
`CNr` int(2),
`MNr` int(5),
`CopyNr` int(2),
`DatoUt` date,
`DateInn` date,
CHECK (`DatoUt` < `DateInn`),
CONSTRAINT `Rent_ibfk_1` FOREIGN KEY (`MNr`) REFERENCES `Model` (`MNr`),
CONSTRAINT `Rent_ibfk_2` FOREIGN KEY (`CopyNr`) REFERENCES `Bike` (`CopyNr`),
CONSTRAINT `Rent_ibfk_3` FOREIGN KEY (`CNr`) REFERENCES `Customer` (`CNr`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `Rent` (`CNr`, `MNr`, `CopyNr`, `DatoUt`, `DateInn`) VALUES
(1, 15, 1, '2020-01-01', '2020-01-30'),
(2, 15, 2, '2020-02-15', '2020-02-29');
/*!40101 SET CHARACTER_SET_CLIENT=#OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=#OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=#OLD_COLLATION_CONNECTION */;
When I put it on SQL on PHPAdmin and click "GO", I got error because of CHECK ( DatoIn > DateUt) code.
And I remove that part, then I get "Rent" table empty of values.
What's wrong am I doing?
Why is the "Rent" table empty of values when I put this on SQL on PHPMyAdmin?
Should I restructure the table relations?
And why "CHECK" doesn't work?
The error message I get where I use CHECK:
I believe you're seeing the syntax warning due to a bug in the parser used by phpMyAdmin which improperly marks this syntax as incorrect. I think that bug specifically is already reported as https://github.com/phpmyadmin/sql-parser/issues/167.
As nick indicates, you can still use the query despite the syntax warning.
I think that the date out should've be less than the date in
CHECK (DatoUt < DateInn),

Dynamic Columns in SQL Select statement, keeping "undefined" values

This is a new Question based on my previos question, which was marked as beeing a "duplicate" of the question
mySQL - Create a New Table Using Data and Columns from Three Tables
This question looks very similiar, but has one essential part which is different
I tried to use the solutions from the linked, but the Ansers does not fit to my problem.
My personal SQL skills are limited. After looking around for several days, I did not find any working solution for my database query problem below. I attached the full example Database SQL-text at the end of this question.
My example database (made with MariaDB) contains two tables:
items, and
itemproperties.
For each item only an item.ID and an item.Name is defined. (In a real life example, the name would be defined to be unique.)
For each item an dynamic user defined set of properties is possible. These properties are defined as a name-value-pair.
For example, for an item named "Banana" a property "Color" with the value "yellow" may exists.
It is only valid to have one "Color" property for one item, so that not two different colors could be assigned to one item.
(In my real world problem the property names contains only two characters, so an additional property name table is not necessary, and subsequently for the ease of showing the problem not used in the example).
The example data for the items table:
ID, Name
1, Car
2, House
3, Homer
4, Earth
And a total of nine properties for the items above are defined. The entry "(NULL)" are indicating that this property is not defined for a given item
ItemID, ItemName, Color, Speed, Price
1, Car, blue, 200, 50000
2, House, red, (NULL), 250000
3, Homer, yellow, 5, (NULL)
4, Earth, blue, 108000, (NULL)
Unfortunally my select statement
SELECT items.ID as ItemID, items.Name as ItemName,
CASE WHEN (itemproperties.Name = 'Color')
THEN itemproperties.Value
#ELSE NULL
END as Color,
CASE WHEN (itemproperties.Name = 'Speed')
THEN itemproperties.Value
#ELSE NULL
END as Speed,
CASE WHEN (itemproperties.Name = 'Price')
THEN itemproperties.Value
#ELSE NULL
END as Price
FROM items left join itemproperties
ON (items.ID=itemproperties.ItemID)
returns the data like this
ItemID, ItemName, Color, Speed, Price
1, Car, blue, (NULL), (NULL)
1, Car, (NULL), 200, (NULL)
1, Car, (NULL), (NULL), 50000
2, House, red, (NULL), (NULL)
2, House, (NULL), (NULL), 250000
3, Homer, yellow, (NULL), (NULL)
3, Homer, (NULL), 5, (NULL)
4, Earth, blue, (NULL), (NULL)
4, Earth, (NULL), 108000, (NULL)
Question: How to write the select statement to get tha data in a collated form, one row for each item?
According too the linked question above, I tried also the following approach
SELECT i.ID as ItemID, i.Name as ItemName,
p1.Value AS Color, p2.Value AS Speed, p3.Value AS Price
FROM items as i
JOIN itemproperties AS p1 ON (i.ID=p1.ItemID)
JOIN itemproperties AS p2 ON (i.ID=p2.ItemID)
JOIN itemproperties AS p3 ON (i.ID=p3.ItemID)
WHERE (p1.Name = 'Color') and (p2.Name = 'Speed') and (p3.Name = 'Price')
But the result is only one line:
ItemID, ItemName, Color, Speed, Price
1, Car, blue, 200, 50000
The reason for this behavior is, that onle the item "Car" have all the three properties "Color", "Speed" and "Price" filled with values.
The item "House" is skipped because it has a "Color" and a "Price", but obviously no "Speed".
So how to get the table in the wanted manner?
Greetings Ekkehard
Database definition:
-- --------------------------------------------------------
-- Host: 127.0.0.1
-- Server Version: 10.1.13-MariaDB - mariadb.org binary distribution
-- Server Betriebssystem: Win32
-- HeidiSQL Version: 9.4.0.5125
-- --------------------------------------------------------
/*!40101 SET #OLD_CHARACTER_SET_CLIENT=##CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!50503 SET NAMES utf8mb4 */;
/*!40014 SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-- Exportiere Datenbank Struktur für DynamicColTest
CREATE DATABASE IF NOT EXISTS `dynamiccoltest` /*!40100 DEFAULT CHARACTER SET latin1 */;
USE `DynamicColTest`;
-- Exportiere Struktur von Tabelle DynamicColTest.itemproperties
CREATE TABLE IF NOT EXISTS `itemproperties` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Unique ID of the property',
`ItemID` int(10) unsigned DEFAULT '0' COMMENT 'ID of the Item this property belongs to',
`Name` varchar(20) DEFAULT '0' COMMENT 'Name of the property',
`Value` varchar(20) DEFAULT '0' COMMENT 'Value of the property',
UNIQUE KEY `Schlüssel 3` (`Name`,`ItemID`),
KEY `Schlüssel 1` (`ID`),
KEY `FK_itemproperties_items` (`ItemID`),
CONSTRAINT `FK_itemproperties_items` FOREIGN KEY (`ItemID`) REFERENCES `items` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 COMMENT='The properties of the items';
-- Exportiere Daten aus Tabelle DynamicColTest.itemproperties: ~9 rows (ungefähr)
DELETE FROM `itemproperties`;
/*!40000 ALTER TABLE `itemproperties` DISABLE KEYS */;
INSERT INTO `itemproperties` (`ID`, `ItemID`, `Name`, `Value`) VALUES
(1, 1, 'Color', 'blue'),
(1, 4, 'Color', 'blue'),
(1, 2, 'Color', 'red'),
(2, 3, 'Color', 'yellow'),
(3, 1, 'Speed', '200'),
(3, 4, 'Speed', '108000'),
(4, 3, 'Speed', '5'),
(5, 1, 'Price', '50000'),
(5, 2, 'Price', '250000');
/*!40000 ALTER TABLE `itemproperties` ENABLE KEYS */;
-- Exportiere Struktur von Tabelle DynamicColTest.items
CREATE TABLE IF NOT EXISTS `items` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Unique Item ID',
`Name` varchar(25) DEFAULT '0' COMMENT 'Name of the Item',
KEY `Schlüssel 1` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 COMMENT='Contains all Items, with a minimum of definitions';
-- Exportiere Daten aus Tabelle DynamicColTest.items: ~4 rows (ungefähr)
DELETE FROM `items`;
/*!40000 ALTER TABLE `items` DISABLE KEYS */;
INSERT INTO `items` (`ID`, `Name`) VALUES
(1, 'Car'),
(2, 'House'),
(3, 'Homer'),
(4, 'Earth');
/*!40000 ALTER TABLE `items` ENABLE KEYS */;
/*!40101 SET SQL_MODE=IFNULL(#OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(#OLD_FOREIGN_KEY_CHECKS IS NULL, 1, #OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=#OLD_CHARACTER_SET_CLIENT */;
You are very close. You need to join your key/value table itemproperties once for each distinct key (property) you need to retrieve. The thing is, you need to use LEFT JOIN. Plain inner JOIN suppresses the output row when the join criterion is unmet.
Try this.
SELECT i.ID as ItemID, i.Name as ItemName,
p1.Value AS Color, p2.Value AS Speed, p3.Value AS Price
FROM items as i
LEFT JOIN itemproperties AS p1 ON (i.ID=p1.ItemID) AND (p1.Name = 'Color')
LEFT JOIN itemproperties AS p2 ON (i.ID=p2.ItemID) AND (p2.Name = 'Speed')
LEFT JOIN itemproperties AS p3 ON (i.ID=p3.ItemID) AND (p3.Name = 'Price')
The expressions selecting the Name values (z.B. p3.Name = 'Price') go in your ON clause rather than your WHERE clause.
The below answer is for SQL SERVER but I hope it could be of some help to you. I am using PIVOT function to achieve the result.You particularly can a similar function in MariaDB.
WITH cte as(
SELECT i.ID as ItemID, i.Name as ItemName,p1.name,p1.value
FROM items as i
JOIN itemproperties AS p1 ON (i.ID=p1.ItemID)
)
select * from cte
PIVOT
(
max(value) for Name in ([Color],[Speed],[Price])
)A
REXTESTER DEMO

Mysql UPDATING statement in datetime

i know its kind of weird but mind if somebody there look for this...
i have a 2 table which is
tableA
id | name | datetime -> format is int(11), varchar(128) datetime()
1 | 'foo bar' | '2014-08-04 00:53:16''
tableB
id | name | datetime | -> format is the same
1 | 'foo bar ' | null
using this statement
UPDATE tableA a
inner join tableB b on b.name = a.name
SET a.datetime = b.datetime
its say
Error Code: 1292. Truncated incorrect time value: '840:53:16';
what the... :)
if i select this using its own format
select * from tableA a inner join tableB b on b.name = a.name
its show
id | name | datetime |id | name | datetime |
1 | 'foo bar' | '2014-08-04 00:53:16'' | 1 | 'foo bar ' | null
am i doing something wrong??
if i use
show create table tableA
CREATE TEMPORARY TABLElist_of_in(
idint(11) NOT NULL,
namevarchar(128) NOT NULL,
datetimedatetime NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
show create table tableB
CREATE TEMPORARY TABLElist_of_in(
idint(11) NOT NULL,
namevarchar(128) NOT NULL,
datetimedatetime NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
by the way , im creating store procedure right now and its working in my localhost
but when i try it to the server, its not working and, after 6 hours i found out that this is the part that is not working...
by the way thanks for reading eheheh :))
I can't replicate your problem.
I recreated your tables, and when I run your query, it replaces tableA's datetime with the null from tableB. I'm guessing that you've built a simplified model of what is actually happening in your database? If that's the case, then the model you've made no longer highlights the problem.
What I did notice though, is that the error you are getting, is suggesting that the date format for one field doesn't match the other. I would check that both fields are in fact datetime, and that one isn't actually a varchar with the date in it.
Here's the dump of the sql to create my testing environment. If you run this (which will wipe TableA and TableB BTW), then run the query yourself, it should succeed.
# Dump of table tableA
# ------------------------------------------------------------
DROP TABLE IF EXISTS `tableA`;
CREATE TABLE `tableA` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) DEFAULT NULL,
`datetime` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
LOCK TABLES `tableA` WRITE;
/*!40000 ALTER TABLE `tableA` DISABLE KEYS */;
INSERT INTO `tableA` (`id`, `name`, `datetime`)
VALUES
(1,'foobar','2014-08-04 00:53:16');
/*!40000 ALTER TABLE `tableA` ENABLE KEYS */;
UNLOCK TABLES;
# Dump of table tableB
# ------------------------------------------------------------
DROP TABLE IF EXISTS `tableB`;
CREATE TABLE `tableB` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) DEFAULT NULL,
`datetime` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
LOCK TABLES `tableB` WRITE;
/*!40000 ALTER TABLE `tableB` DISABLE KEYS */;
INSERT INTO `tableB` (`id`, `name`, `datetime`)
VALUES
(1,'foobar',NULL);
/*!40000 ALTER TABLE `tableB` ENABLE KEYS */;
UNLOCK TABLES;

MySql join statement returning too many results

I am attempting to join some columns from two tables like follows:
select routes.route_collection, times.times
from routes
inner join times
on routes.bus_id & times.bus_id =1;
Although I am getting 12 results (duplicated by 4) instead of three.
Am I doing something wrong here? I have looked at several sites and they all appear to work using similar syntax.
Edit: It appears to be multiplying the amount of values in one table by another - in this case 4 x 3?
Here is the database schema
-- --------------------------------------------------------
-- Host: 127.0.0.1
-- Server version: 5.5.32 - MySQL Community Server (GPL)
-- Server OS: Win32
-- HeidiSQL Version: 8.0.0.4459
-- --------------------------------------------------------
/*!40101 SET #OLD_CHARACTER_SET_CLIENT=##CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-- Dumping database structure for mydb
CREATE DATABASE IF NOT EXISTS `mydb` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `mydb`;
-- Dumping structure for table mydb.buses
CREATE TABLE IF NOT EXISTS `buses` (
`bus_id` int(11) NOT NULL,
PRIMARY KEY (`bus_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Dumping data for table mydb.buses: ~5 rows (approximately)
/*!40000 ALTER TABLE `buses` DISABLE KEYS */;
INSERT INTO `buses` (`bus_id`) VALUES
(1),
(2),
(3),
(4),
(5);
/*!40000 ALTER TABLE `buses` ENABLE KEYS */;
-- Dumping structure for table mydb.routes
CREATE TABLE IF NOT EXISTS `routes` (
`route_id` int(11) NOT NULL,
`bus_id` int(11) DEFAULT NULL,
`route_collection` varchar(45) DEFAULT NULL,
`stop_order` int(11) DEFAULT NULL,
PRIMARY KEY (`route_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Dumping data for table mydb.routes: ~4 rows (approximately)
/*!40000 ALTER TABLE `routes` DISABLE KEYS */;
INSERT INTO `routes` (`route_id`, `bus_id`, `route_collection`, `stop_order`) VALUES
(1, 1, 'Douglas,Onchan,Ballasalla,Castletown,Colby', 1),
(2, 1, 'Douglas,Onchan,Ballasalla,Castletown,Colby', 2),
(3, 1, 'Douglas,Onchan,Ballasalla,Castletown,Colby', 3),
(4, 1, 'Douglas,Onchan,Ballasalla,Castletown,Colby', 4);
/*!40000 ALTER TABLE `routes` ENABLE KEYS */;
-- Dumping structure for table mydb.times
CREATE TABLE IF NOT EXISTS `times` (
`time_id` int(11) NOT NULL,
`start_time` int(11) DEFAULT NULL,
`bus_id` int(11) DEFAULT NULL,
`times` varchar(500) DEFAULT NULL,
`period` varchar(45) DEFAULT NULL,
PRIMARY KEY (`time_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Dumping data for table mydb.times: ~3 rows (approximately)
/*!40000 ALTER TABLE `times` DISABLE KEYS */;
INSERT INTO `times` (`time_id`, `start_time`, `bus_id`, `times`, `period`) VALUES
(1, 600, 1, '06:00,07:00,12:00,14:00,23:00', 'MonFri'),
(2, 615, 1, '06:15,07:15,12:15,14:15,23:15', 'MonFri'),
(3, 600, 1, '06:00,07:00,12:00,14:00,23:00', 'Sat');
/*!40000 ALTER TABLE `times` ENABLE KEYS */;
/*!40101 SET SQL_MODE=IFNULL(#OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(#OLD_FOREIGN_KEY_CHECKS IS NULL, 1, #OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=#OLD_CHARACTER_SET_CLIENT */;
Please use operator 'AND' instead of '&'.
And as I understand you need something like that (do not know do you need the where clouse):
select routes.route_collection, times.times
from routes
inner join times
on routes.bus_id = times.bus_id
where routes.bus_id = 1;
May be you need aggregated values of times?
something like this:
select routes.route_collection, GROUP_CONCAT(times.times)
from routes
inner join times
on routes.bus_id = times.bus_id
where routes.bus_id = 1
group by routes.route_id;