I have a table
table location_category {
id,
location_id,
category_id,
is_primary
}
What I want is to set a UNIQUE constraint for the combination location_id and is_primary.
I get that using this will make a multi column UNIQUE constraint
ALTER TABLE `votes` ADD UNIQUE `unique_index`(`location_id`, `is_primary`);
But my concern is that we can have multiple categories for a location but only set 1 category as primary.
For example:
| id | location_id | category_id | is_primary |
| 1 | 1 | 1 | 0 |
| 2 | 1 | 2 | 0 |
| 3 | 1 | 3 | 1 |
| 4 | 1 | 4 | 0 |
Will this violate the UNIQUE contraint? Since I have multiple instances of location_id = 1 and is_primary = 0?
Just trying to figure this out. Thank you for helping.
There is no need to change anything, UNIQUE allows multiple NULL values
CREATE TABLE `votes` (
`id` INTEGER,
`location_id` INTEGER,
`category_id` INTEGER,
`is_primary` INTEGER
);
ALTER TABLE `votes` ADD UNIQUE `unique_index`(`location_id`, `is_primary`);
INSERT INTO `votes`
(`id`, `location_id`, `category_id`, `is_primary`)
VALUES
('1', '1', '1', NULL),
('2', '1', '2', NULL),
('3', '1', '3', '1'),
('4', '1', '4', NULL);
SELECT * from `votes`
id | location_id | category_id | is_primary
-: | ----------: | ----------: | ---------:
1 | 1 | 1 | null
2 | 1 | 2 | null
3 | 1 | 3 | 1
4 | 1 | 4 | null
db<>fiddle here
So you can only have one location with is primary 1
Related
I have this table:
CREATE TABLE `test` (`id` INT(11) NOT NULL AUTO_INCREMENT , `name` VARCHAR(100) NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB;
| id | name |
| -- | ---- |
In which I insert the following two rows:
INSERT INTO `test`(`name`) VALUES ('Oscar'), ('Alba')
| id | name |
| -- | ----- |
| 1 | Oscar |
| 2 | Alba |
Now, I want to update the existing rows and create new ones:
INSERT INTO `test` (`id`, `name`) VALUES (1, 'Oscar'), (2, 'Nadia'), ('', 'Pedro') ON DUPLICATE KEY UPDATE `id` = VALUES (`id`), `name` = VALUES (`name`)
| id | name |
| -- | ----- |
| 1 | Oscar |
| 2 | Nadia |
| 3 | Pedro |
If I update existing rows again and create new ones, this is what happens:
INSERT INTO `test` (`id`, `name`) VALUES (1, 'Oscar'), (2, 'Nadia'), (3, 'Lucas'), ('', 'Maria'), ('', 'Sergio') ON DUPLICATE KEY UPDATE `id` = VALUES (`id`), `name` = VALUES (`name`)
| id | name |
| -- | ------ |
| 1 | Oscar |
| 2 | Nadia |
| 3 | Lucas |
| 6 | Maria |
| 7 | Sergio |
There is a jump in the auto increment id. I don't know why this happens. I would like to know if there is any way to avoid this.
I've spent way too long thinking about the title of this question, so I hope the one I chose is kinda understandable. But let me explain:
CREATE TABLE IF NOT EXISTS `course` (
`course_id` int(11) NOT NULL,
`course_name` varchar(255) NOT NULL
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
INSERT INTO `course` (`course_id`, `course_name`) VALUES
(1, 'Course A'),
(2, 'Course B'),
(3, 'Course C'),
(4, 'Course D'),
(5, 'Course E');
CREATE TABLE IF NOT EXISTS `course_category` (
`course_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
INSERT INTO `course_category` (`course_id`, `category_id`) VALUES
(1, 1),
(1, 2),
(1, 3),
(2, 2),
(3, 1),
(3, 3),
(5, 1),
(5, 3);
CREATE TABLE IF NOT EXISTS `enrolment` (
`enrolment_id` int(11) NOT NULL,
`course_id` int(11) NOT NULL,
`status` int(11) NOT NULL
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
INSERT INTO `enrolment` (`enrolment_id`, `course_id`, `status`) VALUES
(1, 1, 0),
(2, 1, 1),
(3, 1, 0),
(4, 3, 0),
(5, 3, 0),
(6, 3, 0),
(7, 4, 1),
(8, 4, 1),
(9, 4, 1),
(10, 4, 0);
ALTER TABLE `course`
ADD PRIMARY KEY (`course_id`);
ALTER TABLE `enrolment`
ADD PRIMARY KEY (`enrolment_id`);
ALTER TABLE `course`
MODIFY `course_id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=9;
ALTER TABLE `enrolment`
MODIFY `enrolment_id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=11;
Fiddle: https://www.db-fiddle.com/f/dc3bgfMS5jTxE7wmp3SJ/0
# Table `course`
+-----------+-------------+
| course_id | course_name |
+-----------+-------------+
| 1 | Course A |
| 2 | Course B |
| 3 | Course C |
| 4 | Course D |
| 5 | Course E |
+-----------+-------------+
# Table `course_category`
+-----------+-------------+
| course_id | category_id |
+-----------+-------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 2 |
| 3 | 1 |
| 3 | 3 |
| 5 | 1 |
| 5 | 3 |
+-----------+-------------+
# Table `enrolment`
+--------------+-----------+--------+
| enrolment_id | course_id | status |
+--------------+-----------+--------+
| 1 | 1 | 0 |
| 2 | 1 | 1 |
| 3 | 1 | 0 |
| 4 | 3 | 0 |
| 5 | 3 | 0 |
| 6 | 3 | 0 |
| 7 | 4 | 1 |
| 8 | 4 | 1 |
| 9 | 4 | 1 |
| 10 | 4 | 0 |
+--------------+-----------+--------+
(There's also a category table, but that's not important for the question.)
I am trying to get the following result:
All courses have to be in the result set
The category IDs of each course have to be a single string, separated by commas
The total number of enrolments whose status is 1 should be counted per course (Bear in mind that "1" is only an example here, it could also be another number or a string to be checked against)
+-------------+--------------+------------+
| course_name | category_ids | enrolments |
+-------------+--------------+------------+
| Course A | 3,1,2 | 1 |
| Course B | 2 | 0 |
| Course C | 1,3 | 0 |
| Course D | NULL | 3 |
| Course E | 1,3 | 0 |
+-------------+--------------+------------+
I have tried using SUM with a condition and COUNT with the DISTINCT keyword and a WHERE condition, but I can't get to have all the necessary points fulfilled.
Experiment with COUNT:
SELECT
course_name,
GROUP_CONCAT(DISTINCT category_id) AS category_ids,
COUNT(DISTINCT enrolment_id) as enrolments
FROM
course
LEFT JOIN course_category USING (course_id)
LEFT JOIN enrolment USING (course_id)
WHERE status = 1 OR status IS NULL
GROUP BY course_id
+-------------+--------------+------------+
| course_name | category_ids | enrolments |
+-------------+--------------+------------+
| Course A | 3,1,2 | 1 |
| Course D | NULL | 3 |
+-------------+--------------+------------+
In this case I only get the course if at least one enrolment with status = 1 or no enrolment for the course exists, otherwise the whole course is missing in the result.
Experiment with SUM:
SELECT
course_name,
GROUP_CONCAT(DISTINCT category_id) AS category_ids,
SUM(IF(status=1,1,0)) as enrolments
FROM
course
LEFT JOIN course_category USING (course_id)
LEFT JOIN enrolment USING (course_id)
GROUP BY course_id
+-------------+--------------+------------+
| course_name | category_ids | enrolments |
+-------------+--------------+------------+
| Course A | 3,1,2 | 3 |
| Course B | 2 | 0 |
| Course C | 1,3 | 0 |
| Course D | NULL | 3 |
| Course E | 1,3 | 0 |
+-------------+--------------+------------+
In this case all the courses are there, but the counting is wrong, since I am not able to count distinct enrolments.
Which apporach am I missing?
SELECT c.course_name,
GROUP_CONCAT(cc.category_id ORDER BY cc.category_id) category_ids,
COALESCE(e.status, 0) enrolments
FROM course c
LEFT JOIN course_category cc USING (course_id)
-- calculate statuses per course separately
LEFT JOIN (SELECT course_id, SUM(status) status -- maybe SUM(status=1)?
FROM enrolment
GROUP BY course_id ) e USING (course_id)
GROUP BY c.course_name, e.status
fiddle
I think this would be simpler expressed with correlated subqueries rather than outer aggregation:
select c.course_name,
(
select group_concat(cc.category_id order by cc.category_id)
from course_category cc
where cc.course_id = c.course_id
) category_ids,
(
select coalesce(sum(e.status), 0)
from enrolment e
where e.course_id = c.course_id
) enrolments
from course c
order by c.course_name
--
-- Table structure for table `emp`
--
CREATE TABLE `emp` (
`Emp_id` int(11) NOT NULL,
`Name` varchar(30) DEFAULT NULL,
`Sup_id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `emp`
--
INSERT INTO `emp` (`Emp_id`, `Name`, `Sup_id`) VALUES
(1, 'Mark 18', NULL),
(2, 'Iron Man', 1),
(3, 'Hulk', NULL),
(4, 'Ant-Man', 2);
--
-- Indexes for dumped tables
--
--
-- Indexes for table `emp`
--
ALTER TABLE `emp`
ADD PRIMARY KEY (`Emp_id`),
ADD KEY `Sup_id` (`Sup_id`);
--
this is my table DESC
i want output as this
like in case of iron man
iwant out put like this
2 Iron Man Mark 18
this means it want to check the Emp_id and Dispaly correspond name of Emp _id
DESc Stucture
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| Emp_id | int(11) | NO | PRI | NULL | |
| Name | varchar(30) | YES | | NULL | |
| Sup_id | int(11) | YES | MUL | NULL | |
+--------+-------------+------+-----+---------+-------+
Values Inside Table
+--------+----------+--------+
| Emp_id | Name | Sup_id |
+--------+----------+--------+
| 1 | Mark 18 | NULL |
| 2 | Iron Man | 1 |
| 3 | Hulk | NULL |
| 4 | Ant-Man | 2 |
+--------+----------+--------+
Output format i want
+--------+----------+--------+
| Emp_id | Name | Sup_id |
+--------+----------+--------+
| 1 | Mark 18 |NULL |
| 2 | Iron Man |MArk 18 |
| 3 | Hulk | NULL |
| 4 | Ant-Man |Iron Man|
+--------+----------+--------+
Just LEFT JOIN table on itself:
SELECT e.Emp_id, e.Name, es.Name AS Sup_name FROM emp AS e LEFT JOIN emp AS es ON e.Sup_id = es.Emp_id
I want to make it in such a way that I get:
Main | Column I want to reset on new main value
1 | 100
1 | 101
1 | 102
1 | 103
1 | 104
2 | 100
2 | 101
You can use MyIsam engine to achieve this -
CREATE TABLE table1(
id1 INT(11) NOT NULL,
id2 INT(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id1, id2)
);
INSERT INTO table1 VALUES (1, NULL);
INSERT INTO table1 VALUES (1, NULL);
INSERT INTO table1 VALUES (2, NULL);
INSERT INTO table1 VALUES (2, NULL);
SELECT * FROM table1;
+-----+-----+
| id1 | id2 |
+-----+-----+
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 2 |
+-----+-----+
I am trying to get a list of product id's that do not have certain colors (database is mysql)
Here are my tables:
product
+------------+-------------+
| product_id | description |
+------------+-------------+
| 1 | Widget 1 |
| 2 | Widget 2 |
| 3 | Widget 3 |
| 4 | Widget 4 |
| 5 | Widget 5 |
| 6 | Widget 6 |
+------------+-------------+
color
+----------+-------+
| color_id | name |
+----------+-------+
| 1 | red |
| 2 | black |
| 3 | white |
| 4 | green |
| 5 | blue |
| 6 | pink |
+----------+-------+
product_color
+------------+----------+
| product_id | color_id |
+------------+----------+
| 1 | 1 |
| 1 | 4 |
| 1 | 5 |
| 2 | 2 |
| 2 | 3 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
| 5 | 3 |
| 5 | 6 |
| 6 | 1 |
| 6 | 5 |
| 6 | 6 |
+------------+----------+
I want to select all the products that don't have colors 4 (green), 5 (blue), or 6 (pink).
So from the tables above, products 2, 3, and 4 would appear in the result set.
The best I've been able to do is:
SELECT product.*, GROUP_CONCAT(product_color.color_id) as color_ids
FROM product
LEFT JOIN product_color USING (product_id)
GROUP BY product.product_id
Here is my result set:
--------------------------------------
product_id description color_ids
--------------------------------------
1 Widget 1 1,4,5
2 Widget 2 2,3
3 Widget 3 1,2,3
4 Widget 4 NULL
5 Widget 5 3,6
6 Widget 6 1,3,6
And then I filter them programmatically but I'd prefer for the database to do all the work, if it can.
Optimally, I'd like my result set to look like this (all I need is the product id's).
------------
product_id
------------
2
3
4
Here is the schema and data just case your kind soul would like to help me out.
CREATE TABLE IF NOT EXISTS `color` (
`color_id` int(10) unsigned NOT NULL auto_increment,
`name` varchar(25) NOT NULL,
PRIMARY KEY (`color_id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;
INSERT INTO `color` (`color_id`, `name`) VALUES
(2, 'black'),
(5, 'blue'),
(4, 'green'),
(6, 'pink'),
(1, 'red'),
(3, 'white');
CREATE TABLE IF NOT EXISTS `product` (
`product_id` int(10) unsigned NOT NULL auto_increment,
`description` varchar(25) NOT NULL,
PRIMARY KEY (`product_id`),
UNIQUE KEY `description` (`description`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;
INSERT INTO `product` (`product_id`, `description`) VALUES
(1, 'Widget 1'),
(2, 'Widget 2'),
(3, 'Widget 3'),
(4, 'Widget 4'),
(5, 'Widget 5'),
(6, 'Widget 6');
CREATE TABLE IF NOT EXISTS `product_color` (
`product_id` int(10) unsigned NOT NULL,
`color_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`product_id`,`color_id`),
KEY `color_id` (`color_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `product_color` (`product_id`, `color_id`) VALUES
(1, 1),
(3, 1),
(6, 1),
(2, 2),
(3, 2),
(2, 3),
(3, 3),
(5, 3),
(1, 4),
(1, 5),
(6, 5),
(5, 6),
(6, 6);
I think a sub query in the where clause should be sufficient.
SELECT DISTINCT product_id
FROM product
WHERE product_id NOT IN (SELECT product_id FROM product_color WHERE color_id IN (4, 5, 6));
EDIT: I just saw the many to many bit! This works.