SQL server, HAVING clause issue - sql

I have to write a query for my database. The query is below.
/* Query 9 – Most Valuable Players
"Who has received at least 2 MVP awards?"
Produce a query to display the full name and number of MVP awards of any players who have been awarded the MVP in at least 2 races.
Make sure that races where no MVP was awarded are not included in the results, and order your results by the number of MVP awards in descending order.
Using your race view in this query is recommended.
Hint: Use HAVING to limit the results to players with an MVP count of at least 2.
I've tried it using this code:
CREATE VIEW playerView1
AS
select
player.id, player.firstName + ' ' + player.surname AS 'Full Name', race.mvp
from
player
JOIN
race ON player.team = race.team
GO
SELECT playerView1.[Full Name]
From playerView1
GROUP BY [Full Name]
HAVING (playerView1.mvp) >1
and also tried
SELECT
player.firstName + ' ' + player.surname AS 'Full_name', raceView.mvp AS 'MVP Number',
raceView.mvp_name AS 'MVP Name'
FROM
raceView
JOIN
player ON raceView.mvp_name = player.firstName
WHERE
raceView.mvp > 1
And no luck. Any ideas on where I've gone wrong? and possibly a fix?
One of the errors I came across using the first query was
Msg 8121, Level 16, State 1, Line 4
Column 'playerView1.mvp' is invalid in the HAVING clause because it is not contained in either an aggregate function or the GROUP BY clause.
Below is my entire database script which include create, populate and view before been able to do the query which results in my issue.
IF DB_ID ('Assignment2') IS NOT NULL
BEGIN
DROP DATABASE Assignment2;
END
/* Now create new database*/
CREATE DATABASE Assignment2;
GO
/* Make system use new database */
USE Assignment2;
/* Begin Creating tables */
/** Create Course Table **/
PRINT 'Creating table course.';
CREATE TABLE course (
id INT IDENTITY, -- [CourseID] [int] IDENTITY(1,1) NOT NULL,
name VARCHAR(50), -- [CourseName] [varchar](50) NULL,
passingScore NUMERIC(18,0), -- [PassingScore] [numeric](18, 0) NOT NULL,
CONSTRAINT course_pk PRIMARY KEY (id),
CONSTRAINT passingScore CHECK (passingScore BETWEEN 0 AND 100)
);
/** Create RaceType Table**/
PRINT 'Creating table Race Type.'
CREATE TABLE raceType (
id INT IDENTITY, -- [RaceTypeID] [int] IDENTITY(1,1) NOT NULL,
name VARCHAR(25) NOT NULL, -- [RaceTypeName] [varchar](25) NOT NULL,
CONSTRAINT raceType_pk PRIMARY KEY (id),
CONSTRAINT raceType_unique UNIQUE (name)
);
/** Create 'Teams' Table */
PRINT ' Creating table called Teams'
CREATE TABLE team (
id INT IDENTITY, -- [TeamID] [int] IDENTITY (1,1) NOT NULL,
name VARCHAR(25) NOT NULL, -- [TeamName] [varchar] (25) NOT NULL,
biography TEXT, -- [Biography] [text] NULL,
hyperlink VARCHAR(max), -- [Hyperlink] [varchar] (max) NULL,
CONSTRAINT team_pk PRIMARY KEY (id),
CONSTRAINT team_unique UNIQUE (name)
);
/** Create "Players" Table**/
PRINT ' Creating table called Players'
CREATE TABLE player (
id INT IDENTITY, -- [PlayerID] [int] IDENTITY(1,1) NOT NULL,
firstName VARCHAR(50) NOT NULL, -- [FirstName] [varchar](50) NOT NULL,
surname VARCHAR(50) NOT NULL, -- [Surname] [varchar](50) NOT NULL,
coach INT, -- fk1 [CoachID] [int] NULL,
team INT, -- fk2 [TeamID] [int] NULL,
CONSTRAINT player_pk PRIMARY KEY (id),
CONSTRAINT player_fk1 FOREIGN KEY (team) REFERENCES team (id),
CONSTRAINT player_fk2 FOREIGN KEY (coach) REFERENCES player (id)
);
/** Create "Races" Table **/
PRINT ' Creating table called Races'
CREATE TABLE race (
id INT IDENTITY, -- [RaceID] [int] IDENTITY(1,1) NOT NULL,
dateOfRace DATETIME NOT NULL, -- [DateOfRace] [datetime] NOT NULL,
raceType INT NOT NULL, -- [RaceTypeID] [int] NOT NULL,
course INT NOT NULL, -- [CourseID] [int] NOT NULL,
team INT NOT NULL, -- [TeamID] [int] NOT NULL,
observer INT NOT NULL, -- [ObserverID] [int] NOT NULL,
mvp INT NULL, -- [MvpPlayerID] [int] NULL,
finalScore INT NOT NULL, -- [FinalScore] [int] NOT NULL,
pointsPenalised INT NOT NULL, -- [PointsPenalised] [int] NOT NULL,
CONSTRAINT race_pk PRIMARY KEY (id),
CONSTRAINT race_fk1 FOREIGN KEY (raceType) REFERENCES raceType(id),
CONSTRAINT race_fk2 FOREIGN KEY (course) REFERENCES course(id),
CONSTRAINT race_fk3 FOREIGN KEY (team) REFERENCES team(id),
CONSTRAINT race_fk4 FOREIGN KEY (observer) REFERENCES player(id),
CONSTRAINT race_fk5 FOREIGN KEY (mvp) REFERENCES player(id)
);
GO
/** End*/
The populate script
/** Begin Populating "Course" table*/
PRINT 'Populating Course Table'
INSERT INTO course (name,passingScore)
VALUES ('Easy Course','80');
INSERT INTO course (name,passingScore)
VALUES ('Medium Course','70');
INSERT INTO course (name,passingScore)
VALUES ('Hard Course','60');
/** Begin Populating "RaceType" Table */
PRINT 'Populating RaceType Table '
INSERT INTO raceType (name)
VALUES ('Ranked')
INSERT INTO raceType (name)
VALUES ('Practise')
/** Begin Populating "Teams" Table */
PRINT ' Populating Teams Table'
INSERT INTO team (name)
VALUES ('Team BMW');
INSERT INTO team (name)
VALUES ('Team Porsche');
INSERT INTO team (name)
VALUES ('Team Mercedez');
INSERT INTO team (name)
VALUES ('Team AMartin');
INSERT INTO team (name)
VALUES ('Team Audi');
INSERT INTO player (firstName, surname)
VALUES ('hoger','amedi');
INSERT INTO player (firstName, surname, coach, team)
VALUES (' Lloyd', 'Banks', 1, 1);
INSERT INTO player (firstName, surname)
VALUES ('Silav', 'Govand');
INSERT INTO player (firstName, surname, coach, team)
VALUES ('hell', 'razor', 2, 2);
INSERT INTO player (firstName, surname, coach, team)
VALUES ( 'Alden', 'Padilla', 3, 1);
INSERT INTO player (firstName, surname)
VALUES ( 'Sina', 'Parker');
INSERT INTO player (firstName, surname, coach, team)
VALUES ( 'Lyle', ' Burks', 4, 2);
INSERT INTO player (firstName, surname, coach, team)
VALUES ('Rhona', 'Anthony', 5, 3);
INSERT INTO player (firstName, surname, team)
VALUES ('Seelie', 'Harper', 5);
INSERT INTO player (firstName, surname, coach, team)
VALUES ('Harper', 'Leonards', 6, 4)
INSERT INTO player (firstName, surname, coach, team)
VALUES ('jack', 'Merril', 7, 5)
INSERT INTO race (dateOfRace,finalScore,pointsPenalised,raceType,course,team,observer,mvp)
VALUES ('2011-12-03 06:01:49','53','4','2','1','4','2','1');
INSERT INTO race (dateOfRace,finalScore,pointsPenalised,raceType,course,team,observer,mvp)
VALUES ('2011-11-25 09:31:26','73','5','2','2','1','3','2');
INSERT INTO race (dateOfRace,finalScore,pointsPenalised,raceType,course,team,observer,mvp)
VALUES ('2011-12-03 19:36:34','52','1','1','1','5','4','3');
INSERT INTO race (dateOfRace,finalScore,pointsPenalised,raceType,course,team,observer,mvp)
VALUES ('2011-12-10 20:07:11','51','4','2','3','2','5','2');
INSERT INTO race (dateOfRace,finalScore,pointsPenalised,raceType,course,team,observer,mvp)
VALUES ('2011-11-15 19:19:33','83','5','2','1','3','6','1');
INSERT INTO race (dateOfRace,finalScore,pointsPenalised,raceType,course,team,observer)
VALUES ('2011-11-27 02:32:09','53','1','2','3','5','7');
INSERT INTO race (dateOfRace,finalScore,pointsPenalised,raceType,course,team,observer)
VALUES ('2011-11-24 10:31:53','51','3','1','1','4','8');
INSERT INTO race (dateOfRace,finalScore,pointsPenalised,raceType,course,team,observer)
VALUES ('2011-11-19 15:17:32','70','2','1','2','5','9');
INSERT INTO race (dateOfRace,finalScore,pointsPenalised,raceType,course,team,observer)
VALUES ('2011-12-08 18:00:51','59','2','1','3','1','10');
INSERT INTO race (dateOfRace,finalScore,pointsPenalised,raceType,course,team,observer)
VALUES ('2011-12-09 19:55:53','67','5','2','3','5','10');
Select *
From player;
Select *
From team;
Select *
From raceType;
Select *
From course;
Select *
From race;
the View script
USE Assignment2;
GO
PRINT 'Creating Player View'
GO
CREATE VIEW playerView AS
SELECT player.id, player.firstName + ' ' + player.surname AS 'Full name', player.team, team.name, player.coach, coach.firstName, coach.surname
FROM player
LEFT OUTER JOIN team
ON player.team = team.id
LEFT OUTER JOIN player as coach
ON player.coach = coach.id;
GO
/*
Create a view which shows the following details of all races:
• All of the columns in the race table
• The name of the race type, course and team involved in the race
• The full name of the player observing the race and the full name of the MVP (if applicable)
• A calculated column with an alias of “unpenalised_score”, which adds the points penalised to the final score
Creating this view requires a select statement using multiple joins and concatenation of names.
Make sure that you use the appropriate type of join to ensure that races without MVPs are still included in the results.
*/
-- Write your Race View here
PRINT 'Creating Race View'
GO
CREATE VIEW raceView AS
SELECT race.id, race.dateOfRace, race.raceType, raceType.name AS raceTypeName, race.course, course.name AS courseName, race.team, team.name AS teamName, race.observer, obs.firstName + ' ' + obs.surname AS observer_name, race.mvp, mvp.firstName + ' ' + mvp.surname AS mvp_name, race.pointsPenalised, race.finalScore + race.pointsPenalised AS unpenalised_score, race.finalScore
FROM race
INNER JOIN raceType
ON race.raceType = raceType.id
INNER JOIN course
ON race.course = course.id
INNER JOIN team
ON race.team = team.id
LEFT OUTER JOIN player AS mvp
ON race.mvp = mvp.id
LEFT OUTER JOIN player AS obs
ON race.observer = obs.id;
GO
SELECT *
FROM playerView
SELECT *
FROM raceView

you need to use COUNT
select player.id,
player.firstName + ' ' + player.surname AS [Full Name],
COUNT(*)
from player JOIN race
ON player.team = race.team
GROUP BY id, player.firstName + ' ' + player.surname
HAVING COUNT(*) >= 2
UPDATE 1
SELECT MVP_NAME, COUNT(*) TotalMVP
FROM raceView
WHERE MVP IS NOT NULL
GROUP BY MVP_NAME
HAVING COUNT(*) >= 2
ORDER BY TotalMVP DESC;
SQLFiddle Demo

Related

How to insert data into another table when the condition is met with trigger

I have these 4 tables:
CREATE TABLE dbo.person
(
personId INT IDENTITY(1,1) NOT NULL,
firstName NVARCHAR(30) NOT NULL,
lastName NVARCHAR(30) NOT NULL,
CONSTRAINT pkPerson PRIMARY KEY (personId),
);
CREATE TABLE dbo.personRegistration
(
person_registrationId INT IDENTITY(1,1) NOT NULL,
personId INT,
firstName NVARCHAR(30) NOT NULL,
lastName NVARCHAR(30) NOT NULL,
confirmed NCHAR(1) DEFAULT 'N' NOT NULL,
CONSTRAINT pkpersonRegistration PRIMARY KEY (person_registrationId),
CONSTRAINT fkpersonRegistration FOREIGN KEY (personId) REFERENCES dbo.person (personId)
CONSTRAINT personConfirmed CHECK (confirmed IN ('Y', 'N'))
);
CREATE TABLE dbo.person_organizationalUnit
(
personId INT NOT NULL,
organizationalUnitId INT NOT NULL,
CONSTRAINT pkorganizationalUnit PRIMARY KEY (personId, organizationalUnitId),
CONSTRAINT fkperson FOREIGN KEY (personId) REFERENCES dbo.person (personId),
CONSTRAINT fkorganizationalUnit FOREIGN KEY (organizationalUnitId) REFERENCES dbo.organizatinalUnit(unicOrgUnitId),
);
CREATE TABLE dbo.organizatinalUnit
(
organizationalUnitId INT IDENTITY(1,1) NOT NULL,
organizationalUnitName NVARCHAR(130) NOT NULL,
CONSTRAINT pkorganizationalUnit PRIMARY KEY (organizationalUnitId)
);
I need to create a trigger which will do that when I add new person in table personRegistration (his personId is set to NULL, and initial value for confirmed is 'N') and when I update personRegistration and set confirmed to 'Y', that person is going to be inserted into table person (value for personId is generated because the personId is an identity column) and the confirmed is going to change it's value to 'Y' and is going to be inserted in table person_organizationalUnit. I have written the trigger but the problem is when I update the personRegistration for more than one person my data double with each update.
CREATE TRIGGER personConfirmed
ON dbo.personRegistration
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON
INSERT INTO dbo.person (firstName, lastName)
SELECT
firstName, lastName
FROM
dbo.personRegistration
SET NOCOUNT ON
DECLARE #idPerson int
SELECT #idPerson = personId
FROM dbo.person
INSERT INTO dbo.person_organizationalUnit (personId, organizationalUnitId)
SELECT #idPerson, I.organizationalUnitId
FROM Inserted AS I
JOIN dbo.person p ON p.personId = #idPerson
WHERE confirmed = 'Y';
END
Data for insert:
INSERT INTO dbo.personRegistration (personId, firstName, lastName, confirmed)
VALUES (NULL, 'John', 'Smith', 'N');
Data for update:
UPDATE dbo.personRegistration
SET confirmed = 'Y'
WHERE personRegistrationId = 1;
SQL Server triggers works with sets not single register i did some small changes in your trigger
create TRIGGER dbo.usp_PersonConfirmed ON dbo.personRegistration
AFTER UPDATE
AS
BEGIN
-- create person if not exists
INSERT INTO dbo.person (firstName, lastName)
SELECT firstName, lastName
FROM dbo.personRegistration p
where not exists(select * from dbo.Person where firstName = p.firstName
and lastName = p.lastName)
-- create orgonization unit if person dont exist and confirmed is Y
INSERT INTO dbo.person_organizationalUnit (personId, organizationalUnitId)
SELECT i.personId, I.organizationalUnitId
FROM Inserted AS I
where not exists(select * from dbo.person_organizationalUnit where
personId = i.personId)
and confirmed = 'Y';
-- update orgonization unit if person exist and confirmed is Y
update pou set organizationalUnitId = I.organizationalUnitId
from dbo.person_organizationalUnit pou
inner join Inserted AS I on i.personID = pou.personId
where i.confirmed = 'Y';
END
Your trigger has a fatal flaw: it does not deeal properly with multiple rows. It is also not using the inserted table in the first INSERT, and instead selecting from the whole original table.
So you need to OUTPUT the identity column from the first insert in order to use it in the second.
Because you don't have the identity column yet, you need to join onto firstName and lastName, which I need not say isn't a very good primary key
CREATE OR ALTER TRIGGER personConfirmed
ON dbo.personRegistration
AFTER UPDATE
AS
SET NOCOUNT ON
IF NOT UPDATE(confirmed) OR NOT EXISTS (SELECT 1 FROM inserted)
RETURN; --early bailout
DECLARE #ids TABLE (personId int PRIMARY KEY, firstName nvarchar(100), lastName nvarchar(100));
INSERT INTO dbo.person (firstName, lastName)
OUTPUT inserted.personId, inserted.firstName, inserted.lastName
SELECT
i.firstName,
i.lastName
FROM
inserted i
WHERE i.confirmed = 'Y';
INSERT INTO dbo.person_organizationalUnit (personId, organizationalUnitId)
SELECT ids.personId, i.organizationalUnitId
FROM inserted AS i
JOIN #ids ids ON i.firstName = ids.firstName AND i.lastName = ids.lastName;
Ideally, you have some kind of unique primary key on personRegistration. then your trigger would look like this:
CREATE OR ALTER TRIGGER personConfirmed
ON dbo.personRegistration
AFTER UPDATE
AS
SET NOCOUNT ON
IF NOT UPDATE(confirmed) OR NOT EXISTS (SELECT 1 FROM inserted)
RETURN; --early bailout
DECLARE #ids TABLE (personId int PRIMARY KEY, registrationId int);
MERGE dbo.person p
USING (
SELECT *
FROM inserted i
WHERE i.confirmed = 'Y'
) i
ON 1 = 0 -- never match
WHEN NOT MATCHED THEN
INSERT (firstName, lastName)
VALUES (i.firstName, i.lastName)
OUTPUT inserted.personId, i.organizationalUnitId
INTO #ids (personId, organizationalUnitId)
;
INSERT INTO dbo.person_organizationalUnit (personId, organizationalUnitId)
SELECT ids.personId, i.organizationalUnitId
FROM #ids ids;
We need that funny MERGE because we want to OUTPUT columns that we are not inserting. You can only do this using MERGE.

PostgreSQL table join

I have a lecture attendance database as an uni project.
As one of views, i came up with idea that I could make missed_lectures view with all records of Not attended or Sick attendance types. When I am making this query, it returns 2,5k rows, which is not correct.
Query looks like this
CREATE OR REPLACE VIEW missed_lectures AS
SELECT CONCAT(s.student_name, ' ', s.student_surname) AS "Student", sc.course_title AS "Study course", atp.attendance_type AS "Attendance type", a.record_date AS "Date"
FROM students AS s, study_courses AS sc, attendance_type AS atp, attendance AS a
WHERE
s.student_id=a.student_id AND
sc.course_id=a.course_id AND
a.attendance_type_id=atp.attendance_type_id AND
a.attendance_type_id=(SELECT attendance_type_id FROM attendance_type WHERE attendacne_type='Sick') OR
a.attendance_type_id=(SELECT attendance_type_id FROM attendance_type WHERE attendance_type='Not attended')
GROUP BY s.student_name, s.student_surname, sc.course_title, atp.attendance_type, a.record_date;
This is the last query I came up with, but as I mentioned earlier, it returns 2,5k rows with incorrect data.
Can anybody spot the issue here?
EDIT:
table students is
CREATE TABLE students(
student_id serial PRIMARY KEY NOT NULL,
student_name VARCHAR(30) NOT NULL,
student_surname VARCHAR(35) NOT NULL,
matriculation_number VARCHAR(7) NOT NULL CHECK(matriculation_number ~ '[A-Z]{2}[0-9]{5}'),
faculty_id INT NOT NULL,
course INT NOT NULL,
phone_number CHAR(8) CHECK(phone_number ~ '^2{1}[0-9]{7}'),
email VARCHAR(35),
gender VARCHAR(10)
);
sample data:
INSERT INTO students (student_name, student_surname, matriculation_number, faculty_id, course, phone_number, email, gender)
VALUES
('Sandis','Bērziņš','IT19047',7,1,'25404213','sandis.berzins#gmail.com','man'),
('Einārs','Kļaviņš','IT19045',7,1,'24354654','einars.klavins#gmail.com','man'),
('Jana','Lapa','EF18034',8,2,'26224941','lapajana#inbox.lv','woman'),
('Sanija','Bērza','EF18034',8,2,'24543433','berzasanija#inbox.lv','woman'),
('Valdis','Sijāts','TF19034',4,1,'25456545','valdis.sijats#gmail.com','man'),
('Jānis','Bānis','IT17034',7,3,'24658595','banis.janis#inbox.lv','man');
table study_courses is
CREATE TABLE study_courses(
course_id serial PRIMARY KEY NOT NULL,
course_title VARCHAR(55) NOT NULL,
course_code VARCHAR(8) NOT NULL CHECK(course_code ~ '[a-zA-Z]{4}[0-9]{4}'),
credit_points INT
);
sample data:
INSERT INTO study_courses (course_title, course_code, credit_points)
VALUES
('Fundamentals of Law','JurZ2005',2),
('Database technologies II','DatZ2005',2),
('Product processing','PārZ3049',4),
('Arhitecture','Arhi3063',3),
('Forest soils','LauZ1015',4);
Table attendance_type is:
CREATE TABLE attendance_type(
attendance_type_id serial PRIMARY KEY NOT NULL,
attendance_type VARCHAR(15) NOT NULL
);
sample data:
INSERT INTO attendance_type (attendance_type)
VALUES
('Attended'),
('Not attended'),
('Late'),
('Sick');
table attendance is:
CREATE TABLE attendance(
record_id serial PRIMARY KEY NOT NULL,
student_id INT NOT NULL,
course_id INT NOT NULL,
attendance_type_id INT NOT NULL,
lecturer_id INT,
lecture_type_id INT NOT NULL,
audience_id INT NOT NULL,
record_date DATE NOT NULL
);
sample data:
INSERT INTO attendance (student_id, course_id, attendance_type_id, lecturer_id, lecture_type_id, audience_id, record_date)
VALUES
(1,2,1,1,1,14,'20-05-2020'),
(2,2,1,1,1,14,'20-05-2020'),
(6,9,1,13,2,2,'20-05-2020'),
(22,9,2,13,2,2,'20-05-2020'),
(24,9,3,13,2,2,'20-05-2020');
Hoping this will help.
The problem is that OR condition in your WHERE clause.
You have to surround it by parentheses if you're going to do it that way.
However, you're already querying the attendance_type table so you can just use it to filter for those two attendance type conditions.
SELECT
CONCAT(s.student_name, ' ', s.student_surname) AS "Student",
sc.course_title AS "Study course",
atp.attendance_type AS "Attendance type",
a.record_date AS "Date"
FROM
students AS s, study_courses AS sc,
attendance_type AS atp, attendance AS a
WHERE
s.student_id=a.student_id AND
sc.course_id=a.course_id AND
a.attendance_type_id=atp.attendance_type_id AND
-- filter for these two conditions without subqueries
atp.attendance_type in ('Sick','Not attended')
GROUP BY
CONCAT(s.student_name, ' ', s.student_surname), sc.course_title,
atp.attendance_type, a.record_date;

SQL server 2017 ON DELETE CASCADE question

Below is the code for the entire script. the only issue i have is with the FK below (see lines with -- in front) to remove it. if I add that I get an error using a DELETE, if I only apply the 4 constraints instead of 5 I can delete from the Artist table and it deletes from the other 3 as it should. but when I add PersonalInfo with an ON DELETE CASCADE suddenly I get an error, why? I plan to remove AlbumID from all tables so that they all rely on ArtistID to be identified. Allowing me to use the same column for FK as PK.
CREATE TABLE Artists
( ArtistName varchar(20) NOT NULL, ArtistID varchar(20) NOT NULL, NumberOfAlbumTitles varchar(10) NOT NULL, AlbumID varchar(20) NOT NULL,
PRIMARY KEY (ArtistID))
GO
CREATE TABLE Sales
( AlbumID varchar(20) NOT NULL, CopiesSoldYTD varchar(20) NOT NULL, ArtistID varchar(20) NOT NULL, SalesTotal varchar(20) NOT NULL,
PRIMARY KEY (AlbumID))
GO
CREATE TABLE Production
( AlbumID varchar(20), Copies varchar(20) NOT NULL, UnitPrice varchar(10) NOT NULL, AlbumTitle varchar(20) NOT NULL, ArtistID varchar(20) NOT NULL,
PRIMARY KEY (ArtistID))
GO
CREATE TABLE PersonalInfo
( FirstName varchar(20) NOT NULL, LastName varchar(30) NOT NULL, HomeAddress varchar(30) NOT NULL, PhoneNumber varchar(10) NOT NULL, ArtistID varchar(20) NOT NULL,
PRIMARY KEY (ArtistID))
GO
CREATE TABLE PersonalInfo2
( City varchar(20) NOT NULL, LabelName varchar(20), PostalZip varchar(6) NOT NULL, Region varchar(30) NOT NULL, ArtistID varchar(20) NOT NULL,
PRIMARY KEY (ArtistID))
GO
INSERT INTO Artists
VALUES ('Mr Roberts', 1, 4, 10),
('MC Boogie', 2, 3, 11),
('Singin Sam', 3, 1, 12),
('Avenger', 4, 2, 13)
GO
INSERT INTO Sales
VALUES (10, 232 , 1, 2320),
(11, 151, 2, 1510),
(12, 129, 3, 1290),
(13, 487, 4, 4870)
GO
INSERT INTO Production
VALUES (10 , 500 , 10, 'Roberts 1', 1),
(11, 700, 10, 'Time To Boogie', 2),
(12, 250, 10, ' Dance Dance Dance', 3),
(13, 1000, 10, 'The Revenge Of...', 4)
GO
INSERT INTO PersonalInfo
VALUES ('Brad', 'Roberts' , ' 126 Somewhere Lane', 2048888888, 1),
('Doug', 'Boogie', '234 East bay', 9078789090, 2),
('Raymond', 'Disco', ' 123 Dancing Queen Blvd', 3038761234, 3),
('Ryan', 'Apple', '66 Berkshire Bay', 4549091212, 4)
GO
INSERT INTO PersonalInfo2
VALUES ('Winnipeg', 'Ready Records', 'R2E9N8', 1, 1),
('Calgary','Set Records', 'R3J1M7', 2, 2),
('Texas', 'Go Records', '56555', 5, 3),
('London', 'Canadian Recordings','98887', 4, 4)
GO
ALTER TABLE Sales
ADD FOREIGN KEY (ArtistID) REFERENCES Artists(ArtistID)
ON DELETE CASCADE
GO
--ALTER TABLE PersonalInfo
--ADD FOREIGN KEY (ArtistID) REFERENCES Artists(ArtistID)
--GO
ALTER TABLE PersonalInfo2
ADD FOREIGN KEY (ArtistID) REFERENCES Artists(ArtistID)
ON DELETE CASCADE
GO
ALTER TABLE Sales
ADD FOREIGN KEY (ArtistID) REFERENCES Artists(ArtistID)
GO
ALTER TABLE Production
ADD FOREIGN KEY (ArtistID) REFERENCES Artists(ArtistID)
ON DELETE CASCADE
GO
UPDATE Artists
SET ArtistName = 'Mr. Roberts'
WHERE ArtistID = 1
GO
UPDATE Production
SET Copies = 589, UnitPrice = 12
WHERE AlbumID = 10
GO
UPDATE PersonalInfo
SET HomeAddress = '345 Pritchard Rd', PhoneNumber = 2042341234
WHERE ArtistID = 1
GO
CREATE INDEX index1
ON dbo.Artists (ArtistID, AlbumID);
GO
CREATE INDEX index3
ON Sales (AlbumID, ArtistID);
GO
CREATE INDEX index4
ON Production (AlbumID, ArtistID);
GO
CREATE INDEX index5
ON PersonalInfo2 (City, ArtistID);
GO
CREATE INDEX index6
ON PersonalInfo (ArtistID);
GO
CREATE INDEX index7
ON Artists (ArtistName, NumberOfAlbumTitles);
GO
CREATE INDEX index8
ON Production (ArtistID, AlbumID, Copies, UnitPrice);
GO
CREATE INDEX index9
ON Artists (AlbumID);
GO
CREATE INDEX index11
ON Sales (ArtistID);
GO
CREATE INDEX index12
ON Production (ArtistID)
GO
CREATE INDEX index13
ON PersonalInfo2 (ArtistID);
GO
CREATE VIEW view1 AS
SELECT FirstName, LastName, ArtistName, PhoneNumber, CopiesSoldYTD, SalesTotal
FROM PersonalInfo
INNER JOIN Sales
ON PersonalInfo.ArtistID = Sales.ArtistID
INNER JOIN Artists
ON Sales.ArtistID = Artists.ArtistID
GO
CREATE PROCEDURE Proc1
AS
SELECT FirstName, LastName, Artists.ArtistName, NumberOfAlbumTitles, Artists.ArtistID, LabelName, PhoneNumber, City, UnitPrice, CopiesSoldYTD, SalesTotal
FROM Artists
LEFT JOIN PersonalInfo
ON Artists.ArtistID = PersonalInfo.ArtistID
LEFT JOIN PersonalInfo2
ON PersonalInfo.ArtistID = PersonalInfo2.ArtistID
INNER JOIN Production
ON PersonalInfo2.ArtistID = Production.ArtistID
INNER JOIN Sales
ON Production.ArtistID = Sales.ArtistID
GO
CREATE PROCEDURE dbo.FinalProjectErrorHandling2
AS
BEGIN TRY
SELECT CopiesSoldYTD, SalesTotal
FROM Sales
GROUP BY SalesTotal, CopiesSoldYTD
HAVING CopiesSoldYTD > 200
END TRY
BEGIN CATCH
WHILE(ERROR_NUMBER() > 0 )
RAISERROR ('the error was handled',0,1) WITH NOWAIT
SELECT
ERROR_MESSAGE() AS ErrorMessage
END CATCH
GO
Because you are missing "ON DELETE CASCADE" here
--ALTER TABLE PersonalInfo
--ADD FOREIGN KEY (ArtistID) REFERENCES Artists(ArtistID) <---- Missing on delete cascade
--GO
Once you add that
ALTER TABLE PersonalInfo
ADD FOREIGN KEY (ArtistID) REFERENCES Artists(ArtistID)
ON DELETE CASCADE
GO
it works as required

How to save auto generated primary key Id in foreign key column in same table

Following is the table structure:
CREATE TABLE [User] (
[Id] bigint identity(1,1) not null,
[FirstName] nvarchar(100) not null,
[LastName] nvarchar(100) not null,
[Title] nvarchar(5) null,
[UserName] nvarchar(100) not null,
[Password] nvarchar(100) not null,
[Inactive] bit null,
[Created] Datetime not null,
[Creator] bigint not null,
[Modified] DateTime null,
[Modifier] bigint null
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
(
[Id] Asc
)
);
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[FK_User_Creator]') AND parent_object_id = OBJECT_ID(N'[User]'))
ALTER TABLE [User] ADD CONSTRAINT [FK_User_Creator] FOREIGN KEY([Creator]) REFERENCES [User]([Id])
GO
INSERT INTO [User] (Creator) Values ([Id] ?)
This is a case when table is empty and first user is going to add in table. Otherwise I don't have issue.
How can I insert Id in creator column with insert statement at the same time?
One way could be using Sequence instead of identity column. The below script might serve the same purpose:
CREATE SEQUENCE dbo.useridsequence
AS int
START WITH 1
INCREMENT BY 1 ;
GO
CREATE TABLE [User] (
[Id] bigint DEFAULT (NEXT VALUE FOR dbo.useridsequence) ,
[FirstName] nvarchar(100) not null,
[LastName] nvarchar(100) not null,
[Title] nvarchar(5) null,
[UserName] nvarchar(100) not null,
[Password] nvarchar(100) not null,
[Inactive] bit null,
[Created] Datetime not null,
[Creator] bigint DEFAULT NEXT VALUE FOR dbo.useridsequence ,
[Modified] DateTime null,
[Modifier] bigint null
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
(
[Id] Asc
)
);
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[FK_User_Creator]') AND parent_object_id = OBJECT_ID(N'[User]'))
ALTER TABLE [User] ADD CONSTRAINT [FK_User_Creator] FOREIGN KEY([Creator]) REFERENCES [User]([Id])
GO
INSERT INTO [User]
(
-- Id -- this column value is auto-generated
FirstName,
LastName,
Title,
UserName,
[Password],
Inactive,
Created,
Creator,
Modified,
Modifier
)
VALUES
(
'Foo',
'Bar',
'Title',
'UserName ',
'Password',
0,
GETDATE(),
DEFAULT,
GETDATE(),
1
)
SELECT * FROM [User] AS u
Result :
The short answer is that you can't do this. And I suggest your model is logically flawed in the first place. Do you intend to define all actual database users (e.g., create user ... for login ...) as rows in [Users]? You need to think about that - but the typical answer is no. If the answer is yes, then you don't need the creator column at all because it is redundant. All you need is the created date - for which you probably should have defined a default.
But if you want to do this, you will need to do it in two steps (and you will need to make the column nullable). You insert a row (or rows) with values for the "real" data columns. Then update those same rows with the identity values generated for id. An example showing different ways to do this
use tempdb;
set nocount on;
CREATE TABLE dbo.[user] (
[user_id] smallint identity(3,10) not null primary key,
[name] nvarchar(20) not null,
[active] bit not null default (1),
[created] Datetime not null default (current_timestamp),
[creator] smallint null
);
ALTER TABLE dbo.[user] ADD CONSTRAINT [fk_user] FOREIGN KEY(creator) REFERENCES dbo.[user](user_id);
GO
-- add first row
insert dbo.[user] (name) values ('test');
update dbo.[user] set creator = SCOPE_IDENTITY() where user_id = SCOPE_IDENTITY()
-- add two more rows
declare #ids table (user_id smallint not null);
insert dbo.[user] (name) output inserted.user_id into #ids
values ('nerk'), ('pom');
update t1 set creator = t1.user_id
from #ids as newrows inner join dbo.[user] as t1 on newrows.user_id = t1.user_id;
select * from dbo.[user] order by user_id;
-- mess things up a bit
delete dbo.[user] where name = 'pom';
-- create an error, consume an identity value
insert dbo.[user](name) values (null);
-- add 2 morerows
delete #ids;
insert dbo.[user] (name) output inserted.user_id into #ids
values ('nerk'), ('pom');
update t1 set creator = t1.user_id
from #ids as newrows inner join dbo.[user] as t1 on newrows.user_id = t1.user_id;
select * from dbo.[user] order by user_id;
drop table dbo.[user];
And I changed the identity specification to demonstrate something few developers realize. It isn't always defined as (1,1) and the next inserted value can jump for many reasons - errors and caching/restarts for example. Lastly, I think you will regret naming a table with a reserved word since references to it will require the use of delimiters. Reduce the pain.

Movie booking: How to let every show have its own set of seats?

I have made a movie booking database in mysql workbench (6.2). This database is then connected to eclipse where I in java have programmed a GUI for the movie booking system.
Everything works well with the GUI/database but there is one logical problem:
If a reservation is made for a show, naturally, the number of seats left in that theater where that show is to be played, will be reduced by 1 for every reservation. But if there is a show that's on a different date but on the same theater then this theaters seats is also reduced by 1 which is wrong.
E.g. a show on Monday should have its own set of seats and one on Tuesday should have its own. A solution could be to create a new column 'nbrseats' in 'shows' but I want it to get its seats from Theaters if that's possible.
Database
set foreign_key_checks = 0;
drop table if exists Users;
drop table if exists Theaters;
drop table if exists Movies;
drop table if exists reservations;
drop table if exists Shows;
create table Theaters (
theatername char(11) not null,
NbrSeats char(20) not null,
primary key (theatername)
)engine innoDB;
create table Movies (
moviename char(30) not null,
primary key (moviename)
)engine innoDB;
create table Shows (
movieDate DATE not null,
theatername char(11) not null,
moviename char(30) not null,
id integer auto_increment,
foreign key (theatername) references Theaters(theatername),
foreign key (moviename) references Movies(moviename),
primary key (id)
)engine innoDB;
create table Users (
username char(20) not null,
fullname char(30) not null,
phonenbr char(10) not null,
address varchar(20) not null,
primary key (username)
) engine innoDB;
create table reservations (
resNbr integer auto_increment,
username char(20) not null,
showId int(30) not null,
foreign key(showid) references Shows(id),
foreign key (username) references Users(username),
primary key (resNbr)
)engine innoDB;
-- insert data into the tables
insert into Users values
('Temp1','Name Name', '0701231231', 'Street1');
insert into Movies values
('Star Wars'),
('Dallas'),
('Falcon Crest');
insert into Theaters values
('Filmstaden', '100'),
('SF', '129'),
('Royal', '120');
insert into Shows values
('20151203','Royal', 'Falcon Crest', null),
('20151003','SF', 'Dallas', null),
('20150803','Filmstaden', 'Star Wars', null);
Thanks!
Just make a new column to store the number of booked seats in the reservations table. Then you can write a query to calculate the number of free seats based on the reservations made and the seats available in this theater.
Example to get free seats of showid 1, with two reservations of 5 and 2 seats:
set foreign_key_checks = 0;
drop table if exists Users;
drop table if exists Theaters;
drop table if exists Movies;
drop table if exists reservations;
drop table if exists Shows;
create table Theaters (
theatername char(11) not null,
NbrSeats char(20) not null,
primary key (theatername)
)engine innoDB;
create table Movies (
moviename char(30) not null,
primary key (moviename)
)engine innoDB;
create table Shows (
movieDate DATE not null,
theatername char(11) not null,
moviename char(30) not null,
id integer auto_increment,
foreign key (theatername) references Theaters(theatername),
foreign key (moviename) references Movies(moviename),
primary key (id)
)engine innoDB;
create table Users (
username char(20) not null,
fullname char(30) not null,
phonenbr char(10) not null,
address varchar(20) not null,
primary key (username)
) engine innoDB;
create table reservations (
resNbr integer auto_increment,
username char(20) not null,
showId int(30) not null,
seats int not null,
foreign key(showid) references Shows(id),
foreign key (username) references Users(username),
primary key (resNbr)
)engine innoDB;
-- insert data into the tables
insert into Users values
('Temp1','Name Name', '0701231231', 'Street1');
insert into Movies values
('Star Wars'),
('Dallas'),
('Falcon Crest');
insert into Theaters values
('Filmstaden', '100'),
('SF', '129'),
('Royal', '120');
insert into Shows values
('20151203','Royal', 'Falcon Crest', null),
('20151003','SF', 'Dallas', null),
('20150803','Filmstaden', 'Star Wars', null);
insert into reservations values
(null,'Temp1', 1, 5),
(null,'Temp1', 1, 2),
(null,'Temp1', 2, 3);
select
Shows.id,
Shows.theatername,
Theaters.NbrSeats,
sum(reservations.seats),
Theaters.NbrSeats-sum(reservations.seats) freeseats
from Shows
left join Theaters
on Shows.theatername = Theaters.theatername
left join reservations
on Shows.id = reservations.showId
where Shows.id = 1
group by
Shows.id,
Shows.theatername,
Theaters.NbrSeats
Database is correct, it was a matter of querying
here is an (somewhat primitive) example query for id = 2:
select nbrseats - (select count(showId) from reservations
where showId = (select id from shows where id = 2)) from theaters
where theatername = (select theatername from shows where id = 2);