mysql table with multiple primary key compound constraint - mysql

I'm sorry if the title isn't exactly.. useful, but I wasn't sure how to explain my issue in a title.
So basically, I want to create a table like that :
reservation
day
room
id_client
[other_stuff]
For a given day+room, you can get the id_client + everything else. And also for a given id_client + day you can get the room + other stuff.
I don't exactly understand how am I supposed to say that the compound day+room must be unique AND the compound day+id_client must also be unique. I really need both of those constraint in my database.
Anyone has an idea ?
Thanks.

Define one combination an PRIMARY KEY and the other as UNIQUE key:
CREATE TABLE reservation
( day
, room
, id_client
, [other_stuff]
, PRIMARY KEY (day, room)
, UNIQUE KEY (id_client, day)
) ;
or the other way around:
CREATE TABLE reservation
( day
, room
, id_client
, [other_stuff]
, PRIMARY KEY (id_client, day)
, UNIQUE KEY (day, room)
) ;
Or, if you already have another Primary Key, make them both unique:
CREATE TABLE reservation
( reservation_id
, day
, room
, id_client
, [other_stuff]
, PRIMARY KEY (reservation_id)
, UNIQUE KEY (id_client, day)
, UNIQUE KEY (day, room)
) ;

-- in MySQL
drop database if exists mydatabase;
create database mydatabase;
use mydatabase;
drop table if exists client;
create table client
(
id int unsigned not null auto_increment,
name varchar(45) not null,
primary key (id)
)engine=InnoDB default charset=utf8;
drop table if exists room;
create table room
(
id int unsigned not null auto_increment,
label varchar(45) not null,
primary key (id)
)engine=InnoDB default charset=utf8;
drop table if exists reservation;
create table reservation
(
id int unsigned not null auto_increment,
id_room int unsigned,
id_client int unsigned,
day date,
unique(day, id_room),
unique(day, id_client),
foreign key (id_room) references room(id),
foreign key (id_client) references client(id),
primary key (id)
)engine=InnoDB default charset=utf8;

There are two ways of looking at this... are the unique constraints you mention mutually exclusive? Meaning, can one exist without the other?
Logic dictates that a room can be booked to one day at a time, regardless of client. Unless multiple clients can share the same room. So I will give you two alternatives.
# If room can be booked to multiple clients
CREATE TABLE `reservation` (
`id` int(11) unsigned not null auto_increment,
`day` varchar(25) not null,
`room` int(5) unsigned not null,
`id_client` int(11) unsigned not null,
PRIMARY KEY (`id`),
UNIQUE KEY (`room`, `day`),
UNIQUE KEY (`room`, `id_client`),
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
# Room can only be booked to one client for a given day
CREATE TABLE `reservation` (
`id` int(11) unsigned not null auto_increment,
`day` varchar(25) not null,
`room` int(5) unsigned not null,
`id_client` int(11) unsigned not null,
PRIMARY KEY (`id`),
UNIQUE KEY (`room`, `day`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
Also, I would use a separate primary key column, otherwise your updates will be more complex, for example:
UPDATE `reservation` SET `other_stuff` = 'some value' WHERE `day` = 'Friday' AND `room` = 123;
# Vs
UPDATE `reservation` SET `other_stuff` = 'some value' WHERE `id` = 1;

Related

select all sales from specific day ? mysql , convert datetime to date

how to convert the DateTime column to date?
I need something like the select * from sales where date = = "2022-09-18";
I need to get all sales from a specific day
I tried this How can I convert datetime to date, truncating the times, leaving me the dates?
and many more solutions but nothing is working.
i tried this SELECT DATE(datatime) AS date_of_booking FROM sales; " ;
but it gave me this
I tried also this but it gave me error this
this is a table named Sales
if there is anybody that can help me understand how do I get this thing to work please i really appreciate that! a lot .
code for generating the database if you want
DROP DATABASE IF EXISTS ice_cream_store;
CREATE DATABASE IF NOT EXISTS ice_cream_store;
USE ice_cream_store;
CREATE TABLE `Tastes` (
`tid` INTEGER NOT NULL AUTO_INCREMENT primary key,
`name` VARCHAR(20) NOT NULL,
UNIQUE (name)
);
CREATE TABLE `Toppings` (
`topid` INTEGER NOT NULL AUTO_INCREMENT primary key,
`name` VARCHAR(20) NOT NULL,
UNIQUE (name)
);
CREATE TABLE `Receptacles` (
`rid` INTEGER NOT NULL AUTO_INCREMENT primary key,
`name` VARCHAR(20) NOT NULL,
`price` int NOT NULL,
UNIQUE (name)
);
CREATE TABLE `Sales` (
`sid` INTEGER NOT NULL AUTO_INCREMENT primary key,
`rid` integer not null,
foreign key (`rid`) references Receptacles(`rid`),
`datetime` datetime not null,
`completed` bool not null,
`paid` bool not null,
`total_price` INTEGER NOT NULL
);
CREATE TABLE `Tastes_Sales` (
`sid` integer not null,
foreign key (`sid`) references Sales(`sid`),
`tid` integer not null,
foreign key (`tid`) references Tastes(`tid`),
PRIMARY KEY (`sid` , `tid`),
`quantity` integer not null
);
CREATE TABLE `Toppings_Sales` (
`sid` integer not null,
foreign key (`sid`) references Sales(`sid`),
`topid` integer not null,
foreign key (`topid`) references Toppings(`topid`),
PRIMARY KEY (`sid` , `topid`)
);
SELECT
DATE(`datatime`)
AS date_of_booking
FROM sales;
select * from tastes;
select * from Receptacles;
select * from Toppings;
select * from sales;
select * from Toppings_Sales;
select * from Tastes_Sales;
Use the extract function
Example:
SELECT EXTRACT(MONTH FROM "2017-06-15 09:34:21");
outputs 6
From there you just do:
select * from sales where EXTRACT(DAY FROM date) = 18;
Now you just add AND operators to do the same for month and year
I think this is a simple enough solution. Hope this works for you.
SELECT * from sales WHERE DATE(datetime) = '2022-09-15'; this is working for me #RiggsFolly thank you very much!!

Correct structure and index for a Weekly table

I need a table to store text every week for each user.
So I thought two alternatives:
1) Using composite primary key:
CREATE TABLE `WeeklyTxt` (
`Year` YEAR(4) NOT NULL ,
`Week` ENUM('1','2','3','4', ... ,'51','52','53') NOT NULL ,
`UserId` BIGINT NOT NULL ,
`WeekTxt` TEXT NOT NULL,
PRIMARY KEY (`Year`, `Week`, `UserId`)
) ENGINE = InnoDB;
2) Using autoincrement primary key
CREATE TABLE `WeeklyTxt_2` (
`WeekTxtId` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`Year` YEAR(4) NOT NULL ,
`Week` ENUM('1','2','3','4', ... ,'51','52','53') NOT NULL ,
`UserId` BIGINT NOT NULL ,
`WeekTxt` TEXT NOT NULL
) ENGINE = InnoDB;
I can't figure out what could be the better choice (and why)
It depends of the search in the table that you will usually do!
Tipically I would use a Simple PRIMARY KEY, and I will add another KEY like your KEY: (Year, Week, UserId)

Can I add a Unique key on table creation in SQL?

I am trying to translate a collection of MySQL functions to SQL, and I'm having issues with a UNIQUE KEY issue:
-- -----------------------------------------------------
-- Table testform
-- -----------------------------------------------------
CREATE TABLE `testform` (
`FormId` INT(11) NOT NULL AUTO_INCREMENT,
`TTId` INT(11) NULL DEFAULT NULL,
`TestName` VARCHAR(100) NULL,
PRIMARY KEY (`FormId`),
UNIQUE KEY `TF_Composite` (`TTId`, `TestName`));
When I try and test this in SQLFiddle, it's giving me the error
Incorrect syntax near the keyword 'KEY'.
I have tried searching for this, but so far all I have come up with is "Unique Constraints". Is there a difference between a "Key" and a "Constraint" in SQL? And if so, how can I add this in the table creation statement?
Your syntax is all messed up. Please look at books on-line (MSDN).
https://msdn.microsoft.com/en-us/library/ms174979.aspx
The sample code below create a table in tempdb. This table automatically gets destroyed when the service is restarted.
-- Just a example, throw away after reboot
USE [tempdb]
GO
-- Create the table
CREATE TABLE DBO.TESTFORM
(
FORM_ID INT IDENTITY(1, 1) NOT NULL ,
TT_ID INT NULL,
TEST_NAME VARCHAR(100) NULL,
CONSTRAINT PK_FORM_ID PRIMARY KEY (FORM_ID),
CONSTRAINT UN_COMPOSIT UNIQUE (TT_ID, TEST_NAME)
);
-- Seventies Band
INSERT INTO TEMPDB.DBO.TESTFORM VALUES (1, 'John');
INSERT INTO TEMPDB.DBO.TESTFORM VALUES (2, 'Paul');
INSERT INTO TEMPDB.DBO.TESTFORM VALUES (3, 'Mary');
GO
-- Show data
SELECT * FROM TEMPDB.DBO.TESTFORM
GO
The image below shows the data in this table.
Try This.
CREATE TABLE testform (
FormId INT(11) NOT NULL AUTO_INCREMENT,
TTId INT(11) NULL DEFAULT NULL,
TestName VARCHAR(100) NULL,
PRIMARY KEY (FormId),
CONSTRAINT TF_Composite UNIQUE (TTId,TestName));
More Details..
For Better Understanding about Primary and Unique you can refer below page.
Primary and Unique Key Creation
For MySQL Database
CREATE TABLE `phone` (
`id` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT,
`country` DECIMAL(5,0) UNSIGNED NOT NULL,
`area` DECIMAL(5,0) UNSIGNED NOT NULL,
`number` DECIMAL(8,0) UNSIGNED NOT NULL,
`extension` DECIMAL(5,0) UNSIGNED DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ix_phone` (`country`, `area`, `number`, `extension`),
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
For alter Table :
ALTER TABLEphone
ADD UNIQUE INDEXix_phone(country,area,number,extension);

Trouble with Date fields & Combining data from 2 tables

I'm having a MySQL Database, created using the following code (sure there are other tables too, but they're not relevant as per this specific question) :
DROP TABLE IF EXISTS `Jeweller`.`Product_sales`;
CREATE TABLE `Jeweller`.`Product_sales` (
`sale_id` int(11) unsigned NOT NULL,
`product_id` int(11) NOT NULL,
`quantity` int(11),
`value` float,
FOREIGN KEY (`sale_id`) REFERENCES `Jeweller`.`Sales`(`id`),
FOREIGN KEY (`product_id`) REFERENCES `Jeweller`.`Products`(`id`),
CHECK (`quantity`>0),
CHECK (`value`>0)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `Jeweller`.`Products`;
CREATE TABLE `Jeweller`.`Products` (
`id` int(11) unsigned NOT NULL,
`product_category_id` int(11) NOT NULL,
`seller_id` int(11) NOT NULL,
`name` varchar(100) NOT NULL,
`description` text,
PRIMARY KEY (`id`),
FOREIGN KEY (`product_category_id`) REFERENCES `Jeweller`.`Product_categories`(`id`),
FOREIGN KEY (`seller_id`) REFERENCES `Jeweller`.`Sellers`(`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `Jeweller`.`Sales`;
CREATE TABLE `Jeweller`.`Sales` (
`id` int(11) unsigned NOT NULL,
`date` date DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
How would you go about finding :
Total earnings (quantity*value) per month (in 2013 - or any specific year for that matter)
I started by trying to get the month out of a DATE field (using DATEPART) but I'm already into trouble...
So, any ideas?
P.S.
I'm not a guru with SQL
The above is just an example, and not the exact code
SELECT MONTH(s.date) month, SUM(p.quantity * p.value)
FROM Jeweller.Sales s
JOIN Jeweller.Product_sales p ON p.sale_id = s.id
WHERE s.date >= '2013-01-01' AND s.date < '2014-01-01'
GROUP BY month
Note that if the date range spans multiple years, you will need to group on both year and month.

How do I create this relational table?

Below is a portion of relational data base. I know how to create table Film and assign primary key to it.. but don't understate creating other tables and assigning primary key to it.
Any help?
table Film
CREATE TABLE Film (
Id INTEGER PRIMARY KEY,
Title VARCHAR(35) NOT NULL,
Description VARCHAR(256) NOT NULL,
Year INTEGER NOT NULL CHECK (Year > 1900),
Rating INTEGER NOT NULL DEFAULT 3 CHECK (Rating BETWEEN 1 AND 5)
);
how do I create table FilmFormat and OrderItem ?
CREATE TABLE `jy` (
`PKfield` INTEGER UNSIGNED NOT NULL DEFAULT NULL AUTO_INCREMENT,
`field2` VARCHAR(45) NOT NULL,
PRIMARY KEY (`PKfield`),
CONSTRAINT `FK` FOREIGN KEY `FK` (`PKfield`)
REFERENCES `Film` (`Id`)
ON DELETE RESTRICT
ON UPDATE RESTRICT
)
ENGINE = InnoDB;
This is enough to show you how to create a foreign key constraint between the two tables. As commented, the CHECK constraint will be parsed but ignored.
CREATE TABLE Film (
Id INTEGER PRIMARY KEY,
Title VARCHAR(35) NOT NULL,
Description VARCHAR(256) NOT NULL,
Year INTEGER NOT NULL CHECK (Year > 1900),
Rating INTEGER NOT NULL DEFAULT 3 CHECK (Rating BETWEEN 1 AND 5)
);
CREATE TABLE FilmFormat (
FilmId INTEGER not null,
FormatId INTEGER not null,
Price decimal(16,4) null,
Primary Key(FilmId, FormatId),
Constraint FK_FilmFormat_FilmId FOREIGN KEY (FilmId) REFERENCES Film(Id)
);
Doing the last table will just be doing your work for you.