I'm trying to get all the categories about the specific blogpost but it will not work as I wanted it to work. Below you can see the SQL and code. $blog fetch the information about the specific blogpost.
CREATE TABLE IF NOT EXISTS `blogposts` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`id_user_created` int(10) DEFAULT '0',
`id_user_edited` int(10) DEFAULT '0',
`post_subject` varchar(100) NOT NULL,
`post_message` text NOT NULL,
`post_categories` text NOT NULL,
`date_published` datetime NOT NULL,
`date_edited` datetime NOT NULL,
`info_ipaddress_created` text NOT NULL,
`info_ipaddress_edited` text NOT NULL,
`is_shared` enum('0','1') DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
)
CREATE TABLE IF NOT EXISTS `categories` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`id_user` int(10) DEFAULT '0',
`post_name` text NOT NULL,
`date_added` datetime NOT NULL,
`date_edited` datetime NOT NULL,
`info_ipaddress` text NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
)
$get_categories = "SELECT * FROM blogposts, categories
WHERE blogposts.id = '".(int)$blog['id']."'
AND blogposts.post_categories = categories.id
";
foreach($sql->query($get_categories) AS $category) {
echo '<a href="'.url('blog/category/'.$category['post_name']).'" class="grey-link">';
echo $category['post_name'];
echo '</a>';
}
INSERT INTO blogposts` (id, id_user_created, id_user_edited, post_subject, post_message, post_categories, date_published, date_edited, info_ipaddress_created, info_ipaddress_edited, is_shared)
VALUES (1, 1, 1, 'test', 'testar', '1', '', '', '', '', '0'),
(2, 1, 1, 'med kategorier', 'wiho!', '1|2', '', '', '', '', '0');
INSERT INTO categories` (id, id_user, post_name, date_added, date_edited, info_ipaddress)
VALUES (1, 1, 'test', '', '', ''),
(2, 1, 'test2', '', '', '');
Right now it's only prints Categorized in test, on both blogposts I have posted. It should prints out Categorized in test for the first post and Categorized in test, test2 for the second post. post_categories looks like this: 1|2 which is the ID for the specific category.
Thanks in advance.
If I look at your 'blogposts' table, your 'post_categories' field is of type text. I don't know what is in there but I can imagine it to be a string with id's separated by some character like a semi-colon. This approach limit's the flexibility of your queryies. You'd be better of by creating a link table. This means that you introduce a new table that is responsible for the linkage between a blogpost and it's categories. Looking something like:
CREATE TABLE IF NOT EXISTS `blogposts` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`post_message` text NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
)
CREATE TABLE IF NOT EXISTS `categories` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`category_name` text NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
)
CREATE TABLE IF NOT EXISTS `post_categories` (
`post_id` int(10) NOT NULL AUTO_INCREMENT,
`category_id` text NOT NULL
)
This last table can be used to get all categories that come with a blogpost. You can query over it by using a JOIN, like so:
SELECT *
FROM blogposts b
INNER JOIN post_categories pc ON pc.post_id=p.id
INNER JOIN categories c ON c.id=pc.category_id
WHERE b.id=<yourvariable>
You will than have a list with a lot of duplication but each row is for another category which you can use to display somewhere or whatever purpose you have with it. Maybe it is cleaner to separate this into two queries that a. get the blogpost with the id you have and b. get the categories that come with the blogpost by using the link table.
Related
I have MySQL table where user can post some content on website as follows:
CREATE TABLE `Posts` (
`id` int(6) UNSIGNED NOT NULL,
`name` varchar(30) NOT NULL,
`post` varchar(8000) NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
)
Now I want to create a table for user to comment on posts. I don't know right way to do this, lack of knowledge.
Can I create new table like this
CREATE TABLE `Comments` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
`comment` varchar(800) NOT NULL,
`postId` varchar(8) NOT NULL,
)
and when user comments I can display that comment by connecting "id" from post table and "postID" from "comment" table.
Is this right way to do this, or is there better way to make comments on post table?
Basically, You can link with a foreign key like this.
Posts (
id int(6) UNSIGNED NOT NULL,
name varchar(30) NOT NULL,
post varchar(8000) NOT NULL,
date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
);
You can define a foreign key for user if you want(It's a good pratice).
CREATE TABLE Comments (
id int(10) NOT NULL AUTO_INCREMENT,
name varchar(30) NOT NULL,
comment varchar(800) NOT NULL,
postId int(11) NOT NULL,
user_id int(11) DEFAULT NULL
);
ALTER TABLE Comments ADD CONSTRAINT id_fk_post
FOREIGN KEY(postId) REFERENCES Posts (id);
ALTER TABLE Comments ADD CONSTRAINT id_fk_user
FOREIGN KEY(user_id) REFERENCES Users (id);
Now, you can search all comments of post like this:
SELECT * FROM Comments where postId = 3;
CREATE TABLE `Users` (
`user_id` int(6) UNSIGNED NOT NULL,
`name` varchar(30) NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
)
CREATE TABLE `Comments` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
`comment` varchar(800) NOT NULL,
`postId` varchar(8) NOT NULL,
`user_id_fk` int(6) NOT NULL
)
So as the user posts a comment, you save the user's id in the comment table together with the comment made.
To retrieve, try something like:
$query = 'SELECT Users.user_id,
Users.name,
Comments.comment FROM User JOIN Comments ON Users.user_id= Comments.user_id_fk
';
I have a Search page where users can search based on certain criteria. I cannot get the query right to display only one of the desired objects. It is displaying multiple entries for specified criteria. Here is our database setup:
CREATE TABLE Class
(
cid int NOT NULL,
classNum int,
classDept varchar(20),
PRIMARY KEY (cid)
);
CREATE TABLE Book
(
bid int NOT NULL,
cid int NOT NULL,
title varchar(20) NOT NULL,
author varchar(20) NOT NULL,
isbn varchar(13),
price decimal(5,2) NOT NULL,
PRIMARY KEY (bid),
FOREIGN KEY (cid) REFERENCES Class (cid)
);
CREATE TABLE Contact
(
contactID int NOT NULL,
fname varchar(20),
lname varchar(20),
contactInfo varchar(90) NOT NULL,
PRIMARY KEY (contactID)
);
CREATE TABLE Post
(
pid int NOT NULL,
contactID int NOT NULL,
bid int NOT NULL,
postDate date,
PRIMARY KEY (pid),
FOREIGN KEY (contactID) references Contact(contactID),
FOREIGN KEY (bid) references Book(bid)
);
Here is the php code we are using to try to query based on criteria the user has entered.
$author = $_POST["author"];
$title = $_POST["title"];
$classNum = $_POST["number"];
$classDept = $_POST["department"];
$isbn = $_POST["isbn"];
$query = "SELECT title, author, isbn, price, classNum, classDept, contactInfo
FROM Book, Class, Contact, Post
WHERE Book.cid=Class.cid AND Contact.contactID=Post.ContactID and Book.bid=Post.bid AND Book.author='$author' OR Book.title='$title' ";
$stid = oci_parse($conn,$query);
oci_execute($stid,OCI_DEFAULT);
What are we doing wrong? How can we get the proper search results to display?
I'm not entirely sure that the join syntax in Oracle is the same as mysql ( which is what this was built and tested in ) but given the dummy data and minor modifications to some tables ( adding auto_increment to primary keys ) it returns the expected two rows that match the params.
create table if not exists `book` (
`bid` int(11) not null auto_increment,
`cid` int(11) not null,
`title` varchar(64) not null,
`author` varchar(20) not null,
`isbn` varchar(13) default null,
`price` decimal(5,2) not null,
primary key (`bid`),
key `cid` (`cid`),
constraint `book_ibfk_1` foreign key (`cid`) references `class` (`cid`)
) engine=innodb auto_increment=5 default charset=utf8;
insert into `book` (`bid`, `cid`, `title`, `author`, `isbn`, `price`) values
(1, 1, 'deranged dahlias', 'gertrude geikel', '1234-cdbs-9d', 250.00),
(2, 1, 'mental magnolias', 'gertrude geikel', '4234-cdfg-9f', 225.00),
(3, 1, 'raging roses', 'gertrude geikel', '4389-fkpl-8d', 120.25),
(4, 3, 'peaceful petunias', 'alice cooper', '9043-dflk-01', 500.25);
create table if not exists `class` (
`cid` int(11) not null auto_increment,
`classnum` int(11) default null,
`classdept` varchar(20) default null,
primary key (`cid`)
) engine=innodb auto_increment=4 default charset=utf8;
insert into `class` (`cid`, `classnum`, `classdept`) values
(1, 404, 'fookology'),
(2, 403, 'forbidden fruits'),
(3, 200, 'goodness');
create table if not exists `contact` (
`contactid` int(11) not null auto_increment,
`fname` varchar(20) default null,
`lname` varchar(20) default null,
`contactinfo` varchar(90) not null,
primary key (`contactid`)
) engine=innodb auto_increment=3 default charset=utf8;
insert into `contact` (`contactid`, `fname`, `lname`, `contactinfo`) values
(1, 'joe', 'bloggs', 'chief headbanger'),
(2, 'fred', 'flintstone', 'potatopeeler');
create table if not exists `post` (
`pid` int(11) unsigned not null auto_increment,
`contactid` int(11) not null,
`bid` int(11) not null,
`postdate` date default null,
primary key (`pid`),
key `contactid` (`contactid`),
key `bid` (`bid`),
constraint `post_ibfk_1` foreign key (`contactid`) references `contact` (`contactid`),
constraint `post_ibfk_2` foreign key (`bid`) references `book` (`bid`)
) engine=innodb auto_increment=3 default charset=utf8;
insert into `post` (`pid`, `contactid`, `bid`, `postdate`) values
(1, 1, 1, '2015-12-02'),
(2, 2, 4, '2015-12-02');
Query run in mysql gui - not sure if the join syntax is the same in oracle .
set #_author='alice cooper';
set #_title='mental magnolias';
select * from `book` b
left outer join `class` c on c.`cid`=b.`cid`
left outer join `post` p on p.`bid`=b.`bid`
left outer join `contact` ct on ct.`contactID`=p.`contactID`
where b.`title`=#_title or b.`author`=#_author;
Or, for php
$author=$_POST['author'];
$title=$_POST['title'];
$sql="select * from `book` b
left outer join `class` c on c.`cid`=b.`cid`
left outer join `post` p on p.`bid`=b.`bid`
left outer join `contact` ct on ct.`contactID`=p.`contactID`
where b.`title`='{$title}' or b.`author`='{$author}';";
Let's assume I have three tables in my database, representing a hierarchic order:
countries, states, and cities
Each city is connected to one state, each state to one country. This is simple to represent in a database.
Let's further assume each of those tables contains a field tax_rate. In a basic case the tax rate is defined on country level and null on all other levels. However, it could be overwritten on any of the levels below.
When I query for a city node I would like to get its tax rate. It could be defined right within the same node, but more likely it will be defined on any of the next-higher levels.
What is the most efficient way to accomplish this either in MySQL or on PHP level? In my real life application there will not be only one such field but many of them.
Below is a simple database schema of my example. Of course it would also have foreign key definitions.
CREATE TABLE `countries` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`tax_rate` float(4,2) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `countries` (`id`, `tax_rate`, `name`)
VALUES
(1,8.00,'Switzerland'),
(2,16.00,'Germany');
CREATE TABLE `cities` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`state_id` int(11) DEFAULT NULL,
`tax_rate` float(4,2) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
)
NSERT INTO `cities` (`id`, `state_id`, `tax_rate`, `name`)
VALUES
(1,1,NULL,'Bern'),
(2,1,NULL,'Zollikofen'),
(3,2,NULL,'Zurich'),
(4,2,5.30,'Wettingen'),
(5,2,NULL,'Winterthur'),
(6,2,6.60,'Handligen'),
(7,3,NULL,'Bayern-Town 1'),
(8,3,NULL,'Bayern-Town 2'),
(9,3,9.00,'Bayern-Town 3');
CREATE TABLE `states` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`country_id` int(11) DEFAULT NULL,
`tax_rate` float(4,2) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `states` (`id`, `country_id`, `tax_rate`, `name`)
VALUES
(1,1,NULL,'Bern'),
(2,1,9.00,'Zurich'),
(3,2,NULL,'Bavaria');
Use COALESCE(). That's what it's for.
This could be handled on either level: MySQL or PHP
I'd prefer the MySQL approach:
select cities.name, COALESCE(cities.tax_rate,states.tax_rate,countries.tax_rate) from cities
join states on cities.state_id=states.id
join countries on states.country_id = countries.id
This will return the city's tax rate if it is not NULL, else the state's. If that also is null, it'll return the country's tax rate.
I have these 2 queries and i would like to join them into one but i am unsure of how to go about it.
Query 1:
$query = "SELECT * FROM ".$db_tbl_comics." WHERE ".$db_fld_comics_publisher."='".$pub_id."'
AND ".$db_fld_comics_active."='1' GROUP BY ".$db_fld_comics_arc;
Query 2:
$q2 = mysql_query('SELECT '.$db_fld_arcs_title.' FROM '.$db_tbl_arcs.'
WHERE '.$db_fld_arcs_id.'="'.$result[$db_fld_comics_arc].'"');
Comics Table:
CREATE TABLE IF NOT EXISTS `comics` (
`id` varchar(255) NOT NULL,
`arc` int(255) NOT NULL,
`title` varchar(255) NOT NULL,
`issue` decimal(5,1) DEFAULT NULL,
`price` decimal(10,2) NOT NULL,
`plot` longtext NOT NULL,
`publisher` int(255) NOT NULL,
`isbn` varchar(255) NOT NULL,
`published` date NOT NULL,
`cover` varchar(255) NOT NULL DEFAULT './images/nopic.jpg',
`added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`views` int(255) NOT NULL DEFAULT '0',
`active` int(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `arc` (`arc`,`title`,`issue`,`publisher`)
);
Arcs Table:
CREATE TABLE IF NOT EXISTS `arcs` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`plot` longtext NOT NULL,
`added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `title` (`title`)
);
What I need to do is get the Arcs Title from the arcs table for the respective comic arc.
You need to use INNER JOIN for that since I presume that records are present on both tables.
SELECT a.*, b.title
FROM comics a INNER JOIN arcs b
on a.id = b.id
WHERE a.Title = 'VALUEHERE'
displays all details from comics table and the title of the arc
as simple as (joining 2 queries in one, by selecting only the required field and using IN):
SELECT
'.$db_fld_arcs_title.'
FROM '.$db_tbl_arcs.'
WHERE '.$db_fld_arcs_id.' IN (
SELECT '.$db_fld_comics_arc.'
FROM '.$db_tbl_comics.'
WHERE '.$db_fld_comics_publisher.'='".$pub_id."'
AND '.$db_fld_comics_active.'='1' GROUP BY '.$db_fld_comics_arc.'
)
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