Related to database schemas and design - php

I am building a website for users to be able to make their own profile page with details about themselves, users shall also be able to create pages (similar to those on G+ & FB), however, they can either associate their current personal account with their page or create a separate page with a different account. There shall be many different pages (page types).
I've found this picture:
(source: tomtenthij.nl)
Which seems very interesting, however, how can I structure this in a better way, for example: College Page, or Collect & University Page, or University Page or Hospital Page or Company Page etc. Each have their own set of attributes etc. Any help would be appreciated. I was thinking if Page_type could help me separate each depending on if it is a Hospital or Company etc.
EDIT: I am a beginner in Database Schemas, I have no problem with the PHP code. But want to know of a better way to structure a Database schema for multiple users, pages etc.

I had a cursory look on the tables. I found it satisfactory + problematic (or just I'm not understanding right away). It shall be better if we go through all the tables one by one and discuss the things over the matter of days. One week's input and roll in, roll out of ideas can give us good confidence on what we are going to achieve. Right?
First of all I would like to identify all the possible relations
between a user and profile.
Secondly, I have to decide which will be my master table which will go
on to occupy the relations with rest of the tables. Tables those are
in or will come in the future. Don't forget that we have to put such a
design in place which will never mind any kind of extension.
I read the comment about the graph database. Don't mind that is not something we are ready in position to dive in there. You are right on the track, just need to polish ideas. I'm starting this discussion so that other people can also join here.
I often ran out of time, but will try my best to discuss things as
much as my knowledge can take me that far.

I think #Uours is on the right page but I would suggest a slightly different approach which would allow you to define attributes once and then use them on your various pages. Something like:
page_types
page_type_id (PK)
page_type_name (e.g. College, College & University, University, Hospital, Company, ...)
page_attributes
page_attribute_id (PK)
page_attribute_name (e.g. Name, Address, City, Country, Email, ...)
page_attribute_input_type (e.g. text, checkbox, date, email, password, radio, textarea, select, ...)
page_attribute_input_options (e.g. list of values, size=, maxlength=, pattern=, ...)
page_type_attributes
page_id (PK, FK)
page_attribute_id (PK, FK)
page_attribute_sequence (PK)
page_type_attribute_label (defaults to page_attribute_name but can be overriden in case the same attribute is used more than once on a page)
users
user_id (PK)
user_name
...
user_pages
user_page_id (PK)
user_id (FK)
user_page_type_id (FK)
user_page_name (What the user calls this page)
user_page_attributes
user_page_attribute_id (PK)
user_id (FK)
user_page_id (FK)
page_attribute_id (FK)
user_page_attribute_value
Good luck. Hope this helps.

If I understood your requirement correctly , I suppose this could be rough design of one way to implement User Pages :
user
user_id
user__name
user__password
user__email
...
...
page_type ( Holds Page Ids and Names of various Page Types )
page_type_id
page_type__name ( Ex: College , University , Company , ... )
page_attribute ( Holds the Structure/Attributes of various Page Types )
page_attribute_id
page_attribute__page_type_id
page_attribute__number
page_attribute__order
page_attribute__input_type ( Ex: 1: Text Line , 2: Text Area , 3: Drop Down List , ... )
page_attribute__options ( Ex: For input_type having multiple options , specify the list here as CSV )
user_page ( Holds Page Data for each Page for each User )
user_page_id
user_page__user_id
user_page__page_attribute_id
user_page__page_attribute_data

I've made a diagram of what i think the way to go. So here is it, the explaination & sql follow :
Explaination :
Account : store connection credential. Say you accept facebook login or twitter login, you must associate each credential to the same profil. So a user can login with 3 or more sort of account per profil.
page : Here you put every basic information about a page (whatever her type)
page_extrafield : here is the magic. In your PHP when a user choose 'Create a University page', you display the appropriate form with some fields. Then you save into the database only the field the user has filled. Like :
field_name = 'Established'
filed_value = '1909'
and for an enterprise page, the php form could send to sql :
field_name = 'CEO'
filed_value = 'Steve Jobs'
role : profil can(or not) create a page or multiple pages. And multiple user can manage a single page. So you need a role table to store each users role. Mine is basic like 'Admin','Editor' or 'Member' but you can go for more complicated !
So everything you have to do is a multiple form php with appropriate SQL.
Here is the BDD I used for this example, if you want to test it by your own :
-- Généré le : Mar 18 Février 2014 à 16:50
SET FOREIGN_KEY_CHECKS=0;
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT=0;
START TRANSACTION;
--
-- Base de données: `socialnetwork`
--
CREATE DATABASE `socialnetwork` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `socialnetwork`;
-- --------------------------------------------------------
--
-- Structure de la table `account`
--
DROP TABLE IF EXISTS `account`;
CREATE TABLE IF NOT EXISTS `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(250) NOT NULL,
`password` varchar(50) NOT NULL,
`credentialtype` enum('Email','Facebook','GPlus','Twitter') NOT NULL DEFAULT 'Email',
`profil_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `profil_id` (`profil_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
--
-- Contenu de la table `account`
--
INSERT INTO `account` (`id`, `username`, `password`, `credentialtype`, `profil_id`) VALUES
(1, 'luke#jedi.com', '*7AD0EBD5D5AF7AFF797419070CAEAF6A7671328A', 'Email', 1),
(2, '1197666810', '', 'Facebook', 1);
-- --------------------------------------------------------
--
-- Structure de la table `page`
--
DROP TABLE IF EXISTS `page`;
CREATE TABLE IF NOT EXISTS `page` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(50) NOT NULL DEFAULT 'Page' COMMENT 'type of the page ( university, College,etc)',
`name` varchar(200) NOT NULL COMMENT 'Page Name',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Store general data about page ( common to each page)' AUTO_INCREMENT=3 ;
--
-- Contenu de la table `page`
--
INSERT INTO `page` (`id`, `type`, `name`, `created_at`) VALUES
(1, 'UniversityPage', 'Oxford Official Page', '2014-02-18 16:41:12'),
(2, 'CompagnyPage', 'My Little Compagny', '2014-02-18 16:41:12');
-- --------------------------------------------------------
--
-- Structure de la table `page_extrafield`
--
DROP TABLE IF EXISTS `page_extrafield`;
CREATE TABLE IF NOT EXISTS `page_extrafield` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`field_name` varchar(100) NOT NULL COMMENT 'name of the specific field (like ''location'' or ''logo'')',
`filked_value` text NOT NULL,
`page_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `page_id` (`page_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Store every specialized field about the page (depend on the type of the page)' AUTO_INCREMENT=15 ;
--
-- Contenu de la table `page_extrafield`
--
INSERT INTO `page_extrafield` (`id`, `field_name`, `filked_value`, `page_id`) VALUES
(8, 'location', 'https://maps.google.com/maps?f=q&source=s_q&hl=fr&geocode=&q=oxford&sll=37.0625,-95.677068&sspn=61.323728,135.263672&vpsrc=0&t=h&ie=UTF8&hq=&hnear=Oxford,+Royaume-Uni&z=13&iwloc=A', 1),
(9, 'established', '1909', 1),
(10, 'Enrollment', '499 students', 1),
(11, 'Headmaster', 'Dennis Bisgaard', 1),
(12, 'logo', 'http://foo.com/logo.png', 2),
(13, 'Headquarters', 'San Fransisco', 2),
(14, 'CEO', 'John Doe', 2);
-- --------------------------------------------------------
--
-- Structure de la table `profil`
--
DROP TABLE IF EXISTS `profil`;
CREATE TABLE IF NOT EXISTS `profil` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pseudo` varchar(150) NOT NULL,
`name` varchar(100) NOT NULL,
`forname` varchar(100) NOT NULL,
`picture_url` varchar(500) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
--
-- Contenu de la table `profil`
--
INSERT INTO `profil` (`id`, `pseudo`, `name`, `forname`, `picture_url`, `created_at`) VALUES
(1, 'Jedy', 'Luke', 'Skywalker', 'pict1.jpg', '2014-02-18 16:39:06');
-- --------------------------------------------------------
--
-- Structure de la table `role`
--
DROP TABLE IF EXISTS `role`;
CREATE TABLE IF NOT EXISTS `role` (
`profil_id` int(11) NOT NULL,
`page_id` int(11) NOT NULL,
`access` enum('Admin','Editor','Member') NOT NULL DEFAULT 'Member',
PRIMARY KEY (`profil_id`,`page_id`),
KEY `page_id` (`page_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Contenu de la table `role`
--
INSERT INTO `role` (`profil_id`, `page_id`, `access`) VALUES
(1, 1, 'Admin'),
(1, 2, 'Editor');
--
-- Contraintes pour les tables exportées
--
--
-- Contraintes pour la table `account`
--
ALTER TABLE `account`
ADD CONSTRAINT `account_ibfk_1` FOREIGN KEY (`profil_id`) REFERENCES `profil` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Contraintes pour la table `page_extrafield`
--
ALTER TABLE `page_extrafield`
ADD CONSTRAINT `page_extrafield_ibfk_1` FOREIGN KEY (`page_id`) REFERENCES `page` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Contraintes pour la table `role`
--
ALTER TABLE `role`
ADD CONSTRAINT `role_ibfk_2` FOREIGN KEY (`page_id`) REFERENCES `page` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `role_ibfk_1` FOREIGN KEY (`profil_id`) REFERENCES `profil` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
SET FOREIGN_KEY_CHECKS=1;
COMMIT;
Have Fun and say if it works for you !

Related

Proper solution for storing only few values - column or table?

I've got a huge table 'books' storing book information where I plan to have a row for media type, let's call it 'media_ID'. I know that I'm dealing here with only three possible values: book, ebook and audiobook.
So, making a separate table out of this three values seems to me like wasting especially when I have to include it in every query which feels also unnecessary to me. So what's a clean solution for such cases? Maybe using a PHP array in a config file? What are you using?
books
-------
ID
media_ID
title
...
medias
-------
ID
type
MySQL data:
CREATE `books` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`media_ID` tinyint(4) NOT NULL DEFAULT '1',
`title` tinytext NOT NULL,
)
INSERT INTO `books` (`ID`, `media_ID`, `title`) VALUES
(1, 1, 'Some print book title'),
(2, 1, 'Other print book title'),
(3, 2, 'First ebook title'),
(4, 2, 'Second ebook title'),
(5, 3, 'Single audio book title');
CREATE TABLE `medias` (
`ID` tinyint(4) NOT NULL AUTO_INCREMENT,
`type` tinytext NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
INSERT INTO `medias` (`ID`, `Medium`) VALUES
(1, 'book'),
(2, 'ebook'),
(3, 'audiobook');
Or just php array:
$medias = array("book", "ebook", "audiobook");
Using a separate table for just 3 values is NOT out of the ordinary.
Furthermore this will give you the option of adding more attributes in the future-if the need arises...something that will be an issue with ENUM column type.
In my app...I have such a table that stores the payments packages the user selected...and these are only three.
So go for a table if you are not sure about your future needs/requirements.
Personally I'd use a enum for this.
`mediaType` ENUM('book', 'ebook', 'audiobook') not null
It's also possible to use lookup tables to handle enumaration. Just found the solution here: How to handle enumerations without enum fields in a database.
CREATE `books` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`media` tinyint(4) NOT NULL DEFAULT '1',
`title` tinytext NOT NULL,
FOREIGN KEY (media) REFERENCES medias(Medium)
)

Mysql query join with table column

I have a scenario where i have one main table. Main table has 2 extra columns one is for table name (child table name) and other is for table id (child table id). when we enter the value in main table we also tell enter value in child table and then we enter the name of the table in main table name field and child id in the child field of the main table.
now when i query i need to join query with child table in a way that i picks up the table name from the column and join query with that table with concat function and then join on child id.
below is the structure of the table and also there values
CREATE TABLE IF NOT EXISTS `tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`tbl_type` enum('multi','gift','pledge') DEFAULT NULL,
`tbl_type_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
INSERT INTO `tbl` (`id`, `timestamp`, `tbl_type`, `tbl_type_id`) VALUES
(1, '2015-03-09 09:39:42', '', 1),
(2, '2015-03-09 22:43:23', 'multi', 2),
(3, '2015-03-09 23:26:38', 'gift', 1),
(4, '2015-03-10 09:46:15', 'pledge', 2);
-- --------------------------------------------------------
CREATE TABLE IF NOT EXISTS `tbl_gift` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`amount` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `tbl_gift` (`id`, `amount`) VALUES
(1, '1231200'),
(2, '1231200');
-- --------------------------------------------------------
CREATE TABLE IF NOT EXISTS `tbl_multi` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`amount` float(255,0) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
-- --------------------------------------------------------
CREATE TABLE IF NOT EXISTS `tbl_pledge` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`amount` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `tbl_pledge` (`id`, `amount`) VALUES
(1, '10000'),
(2, '10200');
so this is simple hard code query
select * from tbl t left join tbl_gift g on g.id = t.tbl_type_id
but i want to make it dynamic i tried this
select * from tbl t left join (concat('tbl', '_', t.tbl_type)) g on g.id = t.tbl_type_id
should get the table which i need
(concat('tbl', '_', t.tbl_type))
but it get error
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '('tbl', '_', t.tbl_type)) g on g.id = t.tbl_type_id LIMIT 0, 30' at line 1
The comments by Ankit and Usedby answered your question.
SQL does not allow you to provide dynamically constructed table names as you attempted. They provided you with two options: 1) Construct your query dynamically on the PHP side, then SQL see only the static table names or
2) Use the SQL PREPARE command to construct the dynamic table name and the EXECUTE SQL command to execute it.

Duplicate row in database with relational tables

I am trying to duplicate a page in the database and all related rows.
The problem I am having is because the page_group_id is an identifier for both tables. Is there any way of doing this without looping each of the new "page_groups" records?
pages (page_id, page_name, etc)
page_groups (page_group_id, page_id, etc)
page_group_items (page_group_id, item_id, etc)
UPDATE:
--
-- Table structure for table `pages`
--
CREATE TABLE IF NOT EXISTS `pages` (
`page_id` int(11) NOT NULL AUTO_INCREMENT,
`page_name` varchar(255) NOT NULL,
PRIMARY KEY (`page_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
--
-- Dumping data for table `pages`
--
INSERT INTO `pages` (`page_id`, `page_name`) VALUES
(1, 'My Page'),
(2, 'My other page');
-- --------------------------------------------------------
--
-- Table structure for table `page_groups`
--
CREATE TABLE IF NOT EXISTS `page_groups` (
`page_group_id` int(11) NOT NULL AUTO_INCREMENT,
`page_group_name` varchar(255) NOT NULL,
`page_id` int(11) NOT NULL,
PRIMARY KEY (`page_group_id`),
KEY `page_id` (`page_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
--
-- Dumping data for table `page_groups`
--
INSERT INTO `page_groups` (`page_group_id`, `page_group_name`, `page_id`) VALUES
(1, 'My Group', 1),
(2, 'My Group', 2);
-- --------------------------------------------------------
--
-- Table structure for table `page_group_items`
--
CREATE TABLE IF NOT EXISTS `page_group_items` (
`page_group_id` int(11) NOT NULL,
`item_id` int(11) NOT NULL,
KEY `item_id` (`item_id`),
KEY `page_group_id` (`page_group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `page_group_items`
--
INSERT INTO `page_group_items` (`page_group_id`, `item_id`) VALUES
(1, 1),
(1, 2),
(1, 3),
(2, 1),
(2, 2);
Since you're replacing the only unique identifier in each table (the primary key) when copying, I can't see a way of doing it without adding temporary anchor columns to the tables, do the copy and remove them again. Something like this;
ALTER TABLE pages ADD originalpageid INT;
UPDATE pages set originalpageid=page_id;
ALTER TABLE page_groups ADD originalpagegroupid INT;
UPDATE page_groups SET originalpagegroupid=page_group_id;
INSERT INTO pages (page_name,originalpageid)
SELECT page_name,originalpageid FROM pages;
INSERT INTO page_groups (page_group_name,page_id,originalpagegroupid)
SELECT page_group_name,MAX(pages.page_id),originalpagegroupid
FROM page_groups
JOIN pages
ON page_groups.page_id=originalpageid
GROUP BY originalpageid,page_group_name,originalpagegroupid;
INSERT INTO page_group_items(page_group_id,item_id)
SELECT MAX(page_groups.page_group_id),item_id
FROM page_group_items
JOIN page_groups
ON page_group_items.page_group_id=originalpagegroupid
GROUP BY originalpagegroupid,item_id;
ALTER TABLE pages DROP COLUMN originalpageid;
ALTER TABLE page_groups DROP COLUMN originalpagegroupid;
An SQLfiddle to test with
If the use case is doing it all the time in the system, it may not be the solution you're looking for, but for manual intervention it should work well.
As always, always back your database up before running SQL from random strangers on the Internet :)

Advanced many2many query for MYSQL

I im trying to build a imagegallery where people have access to different groups and the groups decide what catalogues and images they are allowed to see.
I though many2many structure would be best for this.
So far, ive manage to build the database like this:
image (image_name, image_file, image_id)
catalog (catalog_id, catalog_name)
supplier (supplier_id, supplier_name)
user (name, user_id)
image2cataloge (image_id, catalog_id)
image2supplier (image_id, supplier_id)
catalog2supplier (catalog_id, supplier_id)
user2supplier (user_id, supplier_id)
So... that been said, saving images and making supplier (or group if you want), adding users to supplier and linking images to supplier and catalogues is no problem. Inserting is no problem.
But selecting the right images based upon the users supplier setting and catalog they are in is harder.
For example, I have a user with user_id 1, which have access to supplier_id 1. supplier_id 1 have access to view catalogue 1, which holds images with image_id 1 and 2.
But supplier_id 1 only have access to image_id 2.
All this settings are stored in the database. How do I do the select query?
This is what i've tested;
//$catalog_id is the catalog_id we are in
//$user_id is the current users user_id
$sql = "SELECT i.*
FROM image i, user u, catalog cat, supplier s, supplier2user s2u, supplier2catalog s2c, image2catalog i2c, image2supplier i2s
WHERE u.id = '".$user_id."'
AND s2u.user_id = '".$user_id."'
AND s2u.supplier_id = s.id
AND s2c.catalog_id = '".$catalog_id."'
AND i2c.catalog_id = '".$catalog_id."'
AND i2s.supplier_id = s.id
AND s2c.supplier_id = s.id
GROUP BY i.id
ORDER BY i.name ASC
But when ive added more than one image, all images are shown for all users in all catalogues.
EDIT (2010/02/05):
Okey, so I've figured out how to at least show correct images in correct catalog. I do this by doing following:
$sql = "SELECT i.*
FROM
image i
INNER JOIN image2catalog i2c
ON i.id = i2c.image_id
AND i2c.catalog_id = '".$pages_level_0[$i]['id']."'
GROUP BY i.id
;";
This let's me output the correct images that belongs in the catalog the user is visiting at the moment. Now I just need to edit this query to filter out all images the user doesn't have access to. I very grateful for any help you can provide!
EDIT 2010/02/09:
---
CREATION SCHEME
CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`email` varchar(250) NOT NULL,
`password` varchar(50) NOT NULL
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `imagebank` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(250) character set utf8 NOT NULL default '',
`url` varchar(250) character set utf8 NOT NULL default '',
`childof` varchar(250) character set utf8 NOT NULL default '',
`hide` tinyint(4) NOT NULL,
`publishdate` varchar(14) NOT NULL,
`expiredate` varchar(14) NOT NULL,
`editdate` varchar(14) NOT NULL,
`editbygroup` varchar(250) NOT NULL,
`openby` varchar(250) NOT NULL,
`opendate` varchar(250) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_swedish_ci;
CREATE TABLE `imagebank_image` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(250) NOT NULL,
`img` varchar(250) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `imagebank_image2catalog` (
`image_id` int(11) NOT NULL,
`catalog_id` int(11) NOT NULL,
PRIMARY KEY (`image_id`,`catalog_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `imagebank_image2supplier` (
`image_id` int(11) NOT NULL,
`supplier_id` int(11) NOT NULL,
PRIMARY KEY (`image_id`,`supplier_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `imagebank_supplier` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(250) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `imagebank_supplier2catalog` (
`supplier_id` int(11) NOT NULL,
`catalog_id` int(11) NOT NULL,
PRIMARY KEY (`supplier_id`,`catalog_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `imagebank_supplier2user` (
`supplier_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
PRIMARY KEY (`supplier_id`,`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
SOME DATA:
INSERT INTO `imagebank` (`id`, `name`, `url`, `childof`, `hide`, `publishdate`, `expiredate`, `editdate`, `editbygroup`, `openby`, `opendate`) VALUES
(1, 'Test 1', 'test-1', '', 0, '20100204230233', '', '', '', '', ''),
(2, 'Test 2', 'test-2', '', 0, '20100204230244', '', '', '', '', '');
INSERT INTO `imagebank_image` (`id`, `name`, `img`) VALUES
(1, 'Test img 1', 'labb_9noq80bik5.jpeg'),
(2, 'Test img 2', 'labb_53626114dz.jpeg');
INSERT INTO `imagebank_image2catalog` (`image_id`, `catalog_id`) VALUES
(1, 1),
(2, 2);
INSERT INTO `imagebank_image2supplier` (`image_id`, `supplier_id`) VALUES
(1, 2),
(2, 1);
INSERT INTO `imagebank_supplier` (`id`, `name`) VALUES
(1, 'Supplier1'),
(2, 'Supplier2'),
(3, 'Supplier3');
INSERT INTO `imagebank_supplier2catalog` (`supplier_id`, `catalog_id`) VALUES
(1, 2),
(2, 1);
INSERT INTO `imagebank_supplier2user` (`supplier_id`, `user_id`) VALUES
(1, 1),
(1, 11),
(1, 12),
(2, 1),
(2, 10),
(3, 1);
INSERT INTO `user` (`id`, `email`, `password`) VALUES
(1, 'User1#test.com', 'ff02dd5s33taa2ba5ff7c2c4d3327e444'),
(10, 'User2#test.com', 'ff02dd5s33taa2ba5ff7c2c4d3327e444'),
(11, 'User3#test.com', 'ff02dd5s33taa2ba5ff7c2c4d3327e444'),
(12, 'User4#test.com', 'ff02dd5s33taa2ba5ff7c2c4d3327e444');
WOW, now thats alot of stuff :P So I know that the tables, specially for "catalogs" which i call just "imagebank" might look abit strange. But I do have my reasons and thats not really the issue :) Its part of an even bigger picture. Hope this helps you to help me. Thanks again.
It looks like if you are passing in the user and catalogue id's then the supplier doesn't matter.
If you required the supplier information in the result, that would be a different matter.
It feels like you shouldn't be involving the user in this query at all as you seem to be looking for the images in a catalogue that are owned by a particular supplier.
If that is the case, then I would drop the requirement for the user id in the query and use the supplier id instead.
I am assuming that the user would have done the following to get to the point where they would be initiating this query:
login - obviously :)
click on 'list suppliers'
click on a supplier
click on a catalog
Either way you are going to have to do a lot of INNER JOIN's. For instance the query to retrieve the list of suppliers for a given user would be something like
SELECT
s.supplier_id,
s.Supplier_name
FROM
supplier s
INNER JOIN
user u
INNER JOIN
user2supplier u2s
ON
u.user_id = u2s.user_id
ON
u2s.supplier_id = s.supplier_id
WHERE
u.user_id = 3 -- for example...
(now, I haven't tested the SQL, but I think that is right...)
Let me know if I'm on the right track - if I have helped, I'd be happy to help some more if I can

How to store multiple dynamic values within one field in MySQL?

How can I go about storing multiple values (numbers and words) within one field of a MySQL database and then extracting them again as and when I need them using MySQL and PHP?
For example, I want to store the dynamic values a user will enter using a form for example 1, 2, foo, tree, and monkey all in the same field in a database.
Then I want to extract it and put them on separate lines for example:
1
2
foo
tree
monkey
Any ideas?
MySQL 5.7.8 has a new data type that is JSON. You can store a JSON string with all the user information in that column.
Example:
CREATE TABLE table1 (jsonString JSON);
INSERT INTO table1 VALUES('{"car": "bmw", "year": "2006", "key": "value" }');
MySQL Reference
You can put all the values into an array and then serialize it:
$string = serialize(array(1, 2, 'foo', 'tree', 'monkey');
This will give you a string which you store in your database. Later, you can recover your array with de-serializing it:
$array = unserialize($string);
If you're referring to a datatype which can handle a whole slew of stuff, you can use text otherwise this is a bad idea and this is not how you should be storing data in a normalized relational database. Can you please provide information on what you're storing?
I'm a SQL noob myself so if any guru has a better schema strategy, let me know.. this is what I came up with:
Dump:
/*
Navicat MySQL Data Transfer
Date: 2009-10-20 03:01:18
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `job_scores`
-- ----------------------------
DROP TABLE IF EXISTS `job_scores`;
CREATE TABLE `job_scores` (
`job_id` int(2) NOT NULL,
`user_id` int(2) NOT NULL,
`rating` tinyint(2) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
-- ----------------------------
-- Records of job_scores
-- ----------------------------
INSERT INTO `job_scores` VALUES ('1', '1', '10');
-- ----------------------------
-- Table structure for `jobs`
-- ----------------------------
DROP TABLE IF EXISTS `jobs`;
CREATE TABLE `jobs` (
`id` int(2) NOT NULL auto_increment,
`name` varchar(50) collate utf8_unicode_ci default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
-- ----------------------------
-- Records of jobs
-- ----------------------------
INSERT INTO `jobs` VALUES ('1', 'plumber');
-- ----------------------------
-- Table structure for `users`
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` int(2) NOT NULL auto_increment,
`name` varchar(50) collate utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
-- ----------------------------
-- Records of users
-- ----------------------------
INSERT INTO `users` VALUES ('1', 'John');
Example query:
SELECT
jobs.name as job_name, users.name as user_name, job_scores.rating
FROM
job_scores
INNER JOIN jobs ON jobs.id = job_scores.job_id
INNER JOIN users on users.id = job_scores.user_id
WHERE
user_id = 1
Result:
plumber John 10

Categories