Multiple Joins With Condition - mysql

I have the following schema
CREATE TABLE IF NOT EXISTS `params` (
`id` int(6) unsigned NOT NULL,
`parameter` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `entry` (
`id` int(6) unsigned NOT NULL,
`param_id` int(6) unsigned NOT NULL,
`value` int(6) unsigned NOT NULL,
`access_id` int(6) unsigned NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `enabled` (
`id` int(6) unsigned NOT NULL,
`param_id` int(6) unsigned NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `params` (`id`, `parameter`) VALUES
('1','Height'),
('2', 'Weight'),
('3', 'Texture'),
('4', 'Colour');
INSERT INTO `entry` (`id`, `param_id`,`value`,`access_id`) VALUES
('1','1','5.2','1'),
('2','2','80','2'),
('3','1','6','2');
INSERT INTO `enabled` (`id`, `param_id`) VALUES
('1','1'),('2','2');
I am trying to get all parameter values with access_id of 1 from the entry table
OR
All Parameters that are enabled which (DOES NOT exist in the entry table with access_idof 1)
So the output should be
id parameter value access_id
1 Height 5 1
2 Weight NULL NULL
The second entry here has a value of null because although it is enabled it does not have an access_id of 1 in the entry table
The schema here http://sqlfiddle.com/#!9/103016

select p.*, e.value, e.access_id from params p
inner join entry e on p.id= e.param_id and e.access_id = 1
union
select p.*, null,null from params p
inner join enabled enb on p.id=enb.param_id
where enb.param_id not in (select param_id from entry where access_id = 1)

Related

how to count same rating from field in sql

I have a problem counting ratings in SQL. This is what my data looks like:
data
CREATE TABLE `restaurant` (
`id_restaurant` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id_restaurant`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
insert into `restaurant`(`id_restaurant`,`name`) values (1,'Mc Donald');
insert into `restaurant`(`id_restaurant`,`name`) values (2,'KFC');
CREATE TABLE `user` (
`id_user` int(11) NOT NULL AUTO_INCREMENT,
`userName` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id_user`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
insert into `user`(`id_user`,`userName`) values (1,'Audey');
CREATE TABLE `factors` (
`factor_id` int(11) NOT NULL AUTO_INCREMENT,
`factor_clean` int(11) NOT NULL DEFAULT '0',
`factor_delicious` int(11) NOT NULL DEFAULT '0',
`id_restaurant` int(11) DEFAULT NULL,
`id_user` int(11) DEFAULT NULL,
PRIMARY KEY (`factor_id`),
KEY `id_restaurant` (`id_restaurant`),
KEY `id_user` (`id_user`),
CONSTRAINT `factors_ibfk_1` FOREIGN KEY (`id_restaurant`) REFERENCES `restaurant` (`id_restaurant`),
CONSTRAINT `factors_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `user` (`id_user`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
insert into `factors`(`factor_id`,`factor_clean`,`factor_delicious`,`id_restaurant`,`id_user`) values (1,1,5,1,1);
insert into `factors`(`factor_id`,`factor_clean`,`factor_delicious`,`id_restaurant`,`id_user`) values (2,0,5,1,1);
insert into `factors`(`factor_id`,`factor_clean`,`factor_delicious`,`id_restaurant`,`id_user`) values (3,1,5,1,1);
insert into `factors`(`factor_id`,`factor_clean`,`factor_delicious`,`id_restaurant`,`id_user`) values (4,3,3,1,1);
And the result should be like this, Show all ratings (1,2,3,4,5) and their count from the fields rating_clean, rating_delicious, and rating_clean
Thanks for your help.
but the result i get
SELECT COUNT(`factor_clean`+`factor_delicious`),'1' AS rating_1 FROM `factors` WHERE 1 GROUP BY `id_restaurant`
result not should like this
the result should not like that,
my question is, how to select just factor_clean and factor_delicious where factor_clean =1 and factor_delicious = 1
Use union all to unpivot the data and then aggregate:
select id_restaurant, rating, count(*)
from ((select r.id_restaurant, r.rating_clean as rating, r.date
from ratings r
) union all
(select r.id_restaurant, r.rating_delicious, r.date
from ratings r
) union all
(select r.id_restaurant, r.rating_clean2, r.date
from ratings r
)
) r
group by id_restaurant, rating
order by id_restaurant, rating;
For example this is solution for table with colums rating_delicious and rating_clean (only one!):
First of all you should create additional table, I called it factors:
CREATE TABLE `factors` (
`factor_id` int(11) NOT NULL AUTO_INCREMENT,
`factor_clean` int(11) NOT NULL DEFAULT '0',
`factor_delicious` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`factor_id`)
)
Next add two records:
INSERT INTO `factors` (`factor_id`, `factor_clean`, `factor_delicious`) VALUES (NULL, '1', '0'), (NULL, '0', '1');
Now you can join this tables and get results:
SELECT x.id_restaurant
, (x.rating_clean * f.factor_clean) + (x.rating_delicious * f.factor_delicious) AS rating
, count(*)
FROM your_table x
JOIN factors f
WHERE 1
GROUP
BY x.id_restaurant
, rating
In order to use next colum (rating_third), you should and column factor_third to factors, insert new row with 1 in this column and finally add something like your_table.rating_third*factors.factor_third to sum in SELECT

MySQL gather data JOIN

I currently have these two tables
CREATE TABLE IF NOT EXISTS `players` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`group_id` int(11) NOT NULL DEFAULT '1',
`account_id` int(11) NOT NULL DEFAULT '0',
`level` int(11) NOT NULL DEFAULT '1',
`vocation` int(11) NOT NULL DEFAULT '0',
...
) ENGINE=InnoDB;
And
CREATE TABLE IF NOT EXISTS `player_storage` (
`player_id` int(11) NOT NULL DEFAULT '0',
`key` int(10) unsigned NOT NULL DEFAULT '0',
`value` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`player_id`,`key`),
FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
I want to execute the following query
SELECT
a.value,
b.name,
b.level,
b.vocation
FROM
player_storage a,
players b
LEFT JOIN players_online c AS t
ON c.player_id = b.id
WHERE
a.player_id = b.id
AND a.key = 6723
ORDER BY a.value DESC LIMIT 20
Thing is I also want to see if the record exists on the table players_online
CREATE TABLE IF NOT EXISTS `players_online` (
`player_id` int(11) NOT NULL,
PRIMARY KEY (`player_id`)
) ENGINE=MEMORY;
However my query seems to work but its not getting if the player_id exists on players_online
I only get the fields value, name, level, vocation but not a single field related to players_online
You should add a field related to your "online" table.
For example:
SELECT ...,
IF(c.player_id IS NULL, 'offline', 'online') online
FROM ...
And sure, you must to fix issue with double alias in players_online c As t
SQLFiddle

Mysql changing column from 'allow null' to 'not null' and setting value

CREATE TABLE `product` (
`product_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`category_id` int(10) unsigned DEFAULT NULL,
CONSTRAINT `product_category` FOREIGN KEY (`category_id`) REFERENCES `category` (`category_id`),
) ENGINE=InnoDB;
CREATE TABLE `category` (
`category_id` int(10) unsigned NOT NULL AUTO_INCREMENT
) ENGINE=InnoDB;
INSERT INTO `category` VALUES (1), (2);
INSERT INTO `product` (`product_id`, `category_id`) VALUES (1, 1), (2,2), (3, NULL);
I want to change definition of column category_id to forbid NULL values and make value 1 as default value.
I'm running following query:
ALTER TABLE `product` CHANGE `category_id` `category_id` INT(10) UNSIGNED NOT NULL DEFAULT 1;
Table product containts next values (after successful alter query):
1 1
2 2
3 0
Desired result:
1 1
2 2
3 1
FOREIGN_KEY_CHECKS is set to 1 and doesn't change.
Could someone explain why 0 is being set instead of 1.
Thats why the undefined value for an unsigned int is zero. The default value is only used at insertstatement.

MySQL joining 2 tables in to one main table

I have 2 tables 'cat' and 'sub_cat' and these two tables should join or something with main table 'product'
I tried all joining methods and non of them gave me right result I want.
I'm sure there is a method. I don't know what to call.
Sample SQL
This is how the last query should be
forget about the normalization theories and every thing and I just want the last query to be like this or mysql method that I can use on this.
cat_id cannot be duplicate
s_id should also cannot be duplicate
like in third row there can be: cat_id but no s_id the s_id should be null
if there is no cat_id and no s_id both should be null like fourth row
p_id can be duplicate
can't use group by or distinct cause it doesn't give null values then as i know
only method i got closer is using left joining both cat and sub_cat to prod table but it gives me duplicate cat_id and s_id and can't use group by or distinct on this cause there should be null values.
here is the test data
CREATE TABLE IF NOT EXISTS `cat` (
`product_id` int(11) DEFAULT NULL,
`cat_id` int(11) DEFAULT NULL,
`cat_name` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `cat` (`product_id`, `cat_id`, `cat_name`) VALUES
(1, 1, 'cat1'),
(2, 2, 'cat2'),
(3, 3, 'cat3'),
(1, 4, 'ca4');
CREATE TABLE IF NOT EXISTS `prod` (
`product_id` int(11) DEFAULT NULL,
`name` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `prod` (`product_id`, `name`) VALUES
(1, 'prod1'),
(2, 'prod2'),
(3, 'pro3'),
(4, 'prod4');
CREATE TABLE IF NOT EXISTS `sub_cat` (
`product_id` int(11) DEFAULT NULL,
`sub_cat_id` int(11) DEFAULT NULL,
`sub_cat_name` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `sub_cat` (`product_id`, `sub_cat_id`, `sub_cat_name`) VALUES
(1, 1, 'sub cat 1'),
(2, 2, 'sub cat 2'),
(1, 3, 'sub3');
I have done a similar thing in this one.prop_cat acts as you Category table,prop_subcat as your subcategory table and property as you product.
CREATE TABLE `prop_cat` (
`pcat_id` int(11) NOT NULL AUTO_INCREMENT,
`pcat_name` varchar(60) DEFAULT NULL,
PRIMARY KEY (`pcat_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
CREATE TABLE `prop_subcat` (
`psubcat_id` int(11) NOT NULL,
`pcat_id` int(11) NOT NULL,
`psubcat_name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`psubcat_id`,`pcat_id`),
KEY `pspc_idx` (`pcat_id`),
CONSTRAINT `catsub` FOREIGN KEY (`pcat_id`) REFERENCES `prop_cat` (`pcat_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `property` (
`prop_id` int(11) NOT NULL AUTO_INCREMENT,
`prop_name` varchar(25) DEFAULT NULL,
`price` double DEFAULT NULL,
`location` varchar(50) DEFAULT NULL,
`image` varchar(60) DEFAULT NULL,
`area` double DEFAULT NULL,
`psubcat_id` int(11) DEFAULT NULL,
`description` text,
PRIMARY KEY (`prop_id`),
KEY `psub_idx` (`psubcat_id`),
CONSTRAINT `psub` FOREIGN KEY (`psubcat_id`) REFERENCES `prop_subcat` (`pcat_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
SELECT
prop_cat.`pcat_id` AS prop_cat_pcat_id,
prop_cat.`pcat_name` AS prop_cat_pcat_name,
prop_subcat.`psubcat_id` AS prop_subcat_psubcat_id,
prop_subcat.`pcat_id` AS prop_subcat_pcat_id,
prop_subcat.`psubcat_name` AS prop_subcat_psubcat_name,
property.`prop_id` AS property_prop_id,
property.`prop_name` AS property_prop_name,
property.`price` AS property_price,
property.`location` AS property_location,
property.`image` AS property_image,
property.`area` AS property_area,
property.`psubcat_id` AS property_psubcat_id,
property.`description` AS property_description
FROM
`prop_cat` prop_cat INNER JOIN `prop_subcat` prop_subcat ON prop_cat.`pcat_id` = prop_subcat.`pcat_id`
INNER JOIN `property` property ON prop_subcat.`pcat_id` = property.`psubcat_id`

why category name is null when select join with enry table

i have two tables ...first is entry
CREATE TABLE IF NOT EXISTS `entry` (
`entry_id` int(11) NOT NULL AUTO_INCREMENT,
`entry_cat_id` int(11) NOT NULL,
`entry_name` varchar(255) NOT NULL,
`entry_body` text NOT NULL,
`img_url` varchar(255) NOT NULL,
`image_link` varchar(255) NOT NULL,
`entry_state` tinyint(1) DEFAULT '0',
`comment_count` int(11) NOT NULL DEFAULT '0',
`entry_count` int(11) NOT NULL DEFAULT '0',
`entry_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`entry_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=41 ;
--
-- Dumping data for table `entry`
--
INSERT INTO `entry` (`entry_id`, `entry_cat_id`, `entry_name`, `entry_body`, `img_url`, `image_link`, `entry_state`, `comment_count`, `entry_count`, `entry_created`) VALUES
(27, 15, 'title fot entry', 'content', '', '', 0, 0, 0, '2013-04-14 14:47:56');
and the escond is entry_category
CREATE TABLE IF NOT EXISTS `entry_category` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`category_name` varchar(150) NOT NULL,
`slug` varchar(150) NOT NULL,
`cat_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=16 ;
--
-- Dumping data for table `entry_category`
--
INSERT INTO `entry_category` (`category_id`, `category_name`, `slug`, `cat_created`) VALUES
(10, 'rrrrrrrr', 'rrrrrrr', '0000-00-00 00:00:00'),
(15, 'gggggg', 'ttttttttt', '2012-12-10 13:47:28');
when select with inner join to get the category and entry name i see category_name is null
SELECT entry.entry_id, entry_category.category_name, entry.entry_name
FROM entry
INNER JOIN entry_category
ON entry.entry_id=entry_category.category_id;
why and what i shall do to see the the category name
join is having wrong clause
you need to join on category_id but in entry table category_id is in entry_cat_id field so you can join like this
SELECT entry.entry_id, entry_category.category_name, entry.entry_name
FROM entry
INNER JOIN entry_category
ON entry.entry_cat_id=entry_category.category_id;
I think you are joining on the wrong field. You are joining on the entry.entry_id field when I think you want to be joining on the entry.entry_cat_id field.
Try changing your query to:
SELECT entry.entry_id, entry_category.category_name, entry.entry_name
FROM entry
INNER JOIN entry_category
ON entry.entry_cat_id=entry_category.category_id;
BTW -- your existing query shouldn't return any results from your sample data. To see NULL records from your entry_category table, you'd need to use an OUTER JOIN.