Related
I have these tables below along with the definition. I want to find top 10 products sold in a year after finding counts and without using aggregation and in an optimized way. I want to know if aggregation is still needed or I can accomplish it without using aggregation. Below is the query. Can anyone suggest a better approach.
CREATE TABLE Customer (
id int not null,
first_name VARCHAR(30),
last_name VARCHAR(30),
Address VARCHAR(60),
State VARCHAR(30),
Phone text,
PRIMARY KEY(id)
);
CREATE TABLE Product (
ProductId int not null,
name VARCHAR(30),
unitprice int,
BrandID int,
Brandname varchar(30),
color VARCHAR(30),
PRIMARY KEY(ProductId)
);
Create Table Sales (
SalesId int not null,
Date date,
Customerid int,
Productid int,
Purchaseamount int,
PRIMARY KEY(SalesId),
FOREIGN KEY (Productid) REFERENCES Product(ProductId),
FOREIGN KEY (Customerid) REFERENCES Customer(id)
)
Sample Data:
insert into
Customer(id, first_name, last_name, address, state, phone)
values
(1111, 'andy', 'johnson', '123 Maryland Heights', 'MO', 3211451234),
(1112, 'john', 'smith', '237 Jackson Heights', 'TX', 3671456534),
(1113, 'sandy', 'fleming', '878 Jersey Heights', 'NJ', 2121456534),
(1114, 'tony', 'anderson', '789 Harrison Heights', 'CA', 6101456534)
insert into
Product(ProductId, name, unitprice, BrandId, Brandname)
values
(1, 'watch',200, 100, 'apple'),
(2, 'ipad', 429, 100, 'apple'),
(3, 'iphone', 799, 100, 'apple'),
(4, 'gear', 300, 110, 'samsung'),
(5, 'phone',1000, 110, 'samsung'),
(6, 'tab', 250, 110, 'samsung'),
(7, 'laptop', 1300, 120, 'hp'),
(8, 'mouse', 10, 120, 'hp'),
(9, 'monitor', 400, 130, 'dell'),
(10, 'keyboard', 40, 130, 'dell'),
(11, 'dvddrive', 100, 130, 'dell'),
(12, 'dvddrive', 90, 150, 'lg')
insert into
Sales(SalesId, Date, CustomerID, ProductID, Purchaseamount)
values (30, '01-10-2019', 1111, 1, 200),
(31, '02-10-2019', 1111, 3, 799),
(32, '03-10-2019', 1111, 2, 429),
(33, '04-10-2019', 1111, 4, 300),
(34, '05-10-2019', 1111, 5, 1000),
(35, '06-10-2019', 1112, 7, 1300),
(36, '07-10-2019', 1112, 9, 400),
(37, '08-10-2019', 1113, 5, 2000),
(38, '09-10-2019', 1113, 4, 300),
(39, '10-10-2019', 1113, 3, 799),
(40, '11-10-2019', 1113, 2, 858),
(41, '01-10-2020', 1111, 1, 400),
(42, '02-10-2020', 1111, 2, 429),
(43, '03-10-2020', 1112, 7, 1300),
(44, '04-10-2020', 1113, 7, 2600),
(45, '05-10-2020', 1114, 7, 1300),
(46, '06-10-2020', 1114, 7, 1300),
(47, '07-10-2020', 1114, 9, 800)
Tried this:
SELECT PCY.Name, PCY.Year, PCY.SEQNUM
FROM (SELECT P.Name AS Name, Extract('Year' from S.Date) AS YEAR, COUNT(P.Productid) AS CNT,
RANK() OVER (PARTITION BY Extract('Year' from S.Date) ORDER BY COUNT(P.Productid) DESC) AS RANK
FROM Sales S inner JOIN
Product P
ON S.Productid = P.Productid
) PCY
WHERE PCY.RANK <= 10;
I am seeing this error:
ERROR: column "p.name" must appear in the GROUP BY clause or be used in an aggregate function
LINE 2: FROM (SELECT P.Name AS Name, Extract('Year' from S.Date) AS ...
^
SQL state: 42803
Character: 52
I don't understand why you don't want to use an aggregate function when you have to aggregate over your data. This query works fine, without any issues on the GROUP BY:
WITH stats AS (
SELECT EXTRACT
( YEAR FROM DATE ) AS y,
P.productid,
P.NAME,
COUNT ( * ) numbers_sold,
RANK ( ) OVER ( PARTITION BY EXTRACT ( YEAR FROM DATE ) ORDER BY COUNT ( * ) DESC ) r
FROM
product
P JOIN sales S ON S.Productid = P.Productid
GROUP BY
1,2
)
SELECT y
, name
, numbers_sold
FROM stats
WHERE r <= 10;
This works because the productid is the primary key that has a functional dependency to the product name.
By the way, tested on version 12, but it should work on older and newer versions as well.
What is wrong with this SQL statement?
Create table JaretsSchedule
(
ScheduleID Int Primary Key NOT NULL,
FieldID Int NOT NULL,
HomeTeamID Int NOT NULL,
AwayTeamID Int NOT NULL,
GameTime DateTime NOT NULL
);
Insert into JaretsSchedule
Values
(1, 1, 1, 2, '2012-10-02 12:00:00'),
(1, 1, 1, 3, '2012-10-17 12:00:00'),
(1, 1, 1, 4, '2012-09-23 12:00:00'),
(1, 2, 2, 1, '2012-09-12 12:00:00'),
(1, 3, 3, 1, '2012-08-19 12:00:00'),
(1, 4, 4, 1, '2012-07-25 12:00:00'),
(2, 2, 2, 1, '2012-09-15 12:00:00'),
(2, 2, 2, 3, '2012-09-06 12:00:00'),
(2, 2, 2, 4, '2012-08-28 12:00:00'),
(2, 1, 1, 2, '2012-10-02 12:00:00'),
(2, 3, 3, 2, '2012-08-11 12:00:00'),
(2, 4, 4, 2, '2012-07-17 12:00:00'),
(3, 3, 3, 1, '2012-08-19 12:00:00'),
(3, 3, 3, 2, '2012-08-11 12:00:00'),
(3, 3, 3, 4, '2012-08-03 12:00:00'),
(3, 1, 1, 3, '2012-10-17 12:00:00'),
(3, 2, 2, 3, '2012-10-17 12:00:00'),
(3, 4, 4, 3, '2012-07-09 12:00:00'),
(4, 4, 4, 1, '2012-07-25 12:00:00'),
(4, 4, 4, 2, '2012-07-17 12:00:00'),
(4, 4, 4, 3, '2012-07-09 12:00:00'),
(4, 1, 1, 4, '2012-09-23 12:00:00'),
(4, 2, 2, 4, '2012-08-28 12:00:00'),
(4, 3, 3, 4, '2012-08-03 12:00:00');
With the resulting error:
Msg 2627, Level 14, State 1, Line 8
Violation of PRIMARY KEY constraint 'PK__JaretsSc__9C8A5B696CFE9A03'. Cannot insert duplicate key in object 'dbo.JaretsSchedule'. The duplicate key value is (1).
The error message is literally telling you what the problem is. You can't insert the same value more than once for the ScheduleID column, which you have defined as the primary key. Once workaround here would be to just make this column an identity/auto increment column. Then, don't even include a value for it when inserting. Instead, let SQL Server handle it:
CREATE TABLE JaretsSchedule (
ScheduleID INT NOT NULL IDENTITY PRIMARY KEY,
FieldID INT NOT NULL,
HomeTeamID INT NOT NULL,
AwayTeamID INT NOT NULL,
GameTime DateTime NOT NULL
);
INSERT INTO JaretsSchedule (FieldID, HomeTeamID, AwayTeamID, GameTime)
VALUES
(1, 1, 2, '2012-10-02 12:00:00'),
(1, 1, 3, '2012-10-17 12:00:00'),
(1, 1, 4, '2012-09-23 12:00:00'),
...
Note also that I explicitly list out the columns, in order, which are the target for the insert. This is also best practice, and avoids a situation later on wher it might not be clear to which columns the data in the VALUES clause corresponds.
I have a view that has suddenly gotten too slow and I'm at a loss of how to optimize it. The tables currently contain 15000 (#dispatchPallet) and 135000 (#pickLog) rows respectively.
I've written a minimized piece of code to show the important parts below.
DECLARE #dispatchPallet TABLE
(
[PICK_PALL_NUM] [bigint] NOT NULL,
[PALLET_PLACEMENT] [nvarchar](4) NOT NULL,
[SHIPMENT_ID] [nvarchar](255) NULL
)
DECLARE #pickLog TABLE
(
[LINE_NUM] [int] NOT NULL,
[QTY_PRE] [numeric](9, 2) NULL,
[QTY_SUF] [numeric](9, 2) NULL,
[PICK_PALL_NUM] [bigint] NULL,
[ROWID] [uniqueidentifier] NOT NULL,
[WEIGHT_GROSS] [numeric](9, 3) NULL,
[VOLUME] [numeric](9, 3) NULL
)
INSERT INTO #dispatchPallet ([PICK_PALL_NUM], [PALLET_PLACEMENT], [SHIPMENT_ID])
VALUES
(4797753, 'B', 'SHIPMENT-1'),
(4797752, 'B', 'SHIPMENT-2'),
(4797750, 'B', 'SHIPMENT-3'),
(4797749, 'B', 'SHIPMENT-4'),
(4797739, 'B', 'SHIPMENT-5'),
(4797732, 'B', 'SHIPMENT-6'),
(4797731, 'B', 'SHIPMENT-7'),
(4797730, 'B', 'SHIPMENT-7'),
(4797723, 'B', 'SHIPMENT-8'),
(4797713, 'B', 'SHIPMENT-9')
INSERT INTO #pickLog ([LINE_NUM], [QTY_PRE], [QTY_SUF], [PICK_PALL_NUM], [ROWID], [WEIGHT_GROSS])
VALUES
(30, 54, 54, 4797753, NEWID(), 1070.280),
(10, 24, 24, 4797752, NEWID(), 471.360),
(30, 12, 12, 4797750, NEWID(), 237.960),
(320, 25, 25, 4797749, NEWID(), 102.750),
(110, 3, 3, 4797739, NEWID(), 40.650),
(40, 12, 12, 4797732, NEWID(), 238.080),
(50, 4, 4, 4797732, NEWID(), 78.560),
(20, 20, 20, 4797731, NEWID(), 110.000),
(20, 40, 40, 4797730, NEWID(), 220.000),
(1340, 3, 3, 4797723, NEWID(), 14.250),
(410, 2, 2, 4797723, NEWID(), 4.780),
(440, 2, 2, 4797723, NEWID(), 21.000),
(480, 1, 1, 4797723, NEWID(), 3.500),
(1290, 2, 2, 4797723, NEWID(), 39.280),
(470, 1, 1, 4797723, NEWID(), 8.500),
(280, 3, 3, 4797723, NEWID(), 16.500),
(10, 2, 2, 4797723, NEWID(), 10.700),
(500, 2, 2, 4797723, NEWID(), 6.600),
(290, 1, 1, 4797713, NEWID(), 0.540),
(40, 2, 2, 4797713, NEWID(), 33.800)
SELECT
[dispatchPallet].[SHIPMENT_ID],
SUM([pickLog].[QTY_SUF]) AS KOLLI,
COUNT(DISTINCT [pickLog].[LINE_NUM]) AS LINES,
SUM([pickLog].[WEIGHT_GROSS]) AS PICKED_WEIGHT,
COUNT(DISTINCT [pickLog].[PICK_PALL_NUM]) AS PALLETS,
COUNT(DISTINCT CASE WHEN [dispatchPallet].[PALLET_PLACEMENT] = 'B' THEN [dispatchPallet].[PICK_PALL_NUM] ELSE NULL END) AS BOTTOM_PALLETS
FROM
#dispatchPallet dispatchPallet
INNER JOIN #pickLog pickLog ON [dispatchPallet].[PICK_PALL_NUM] = [pickLog].[PICK_PALL_NUM]
GROUP BY
[dispatchPallet].[SHIPMENT_ID]
-- Expected output:
-- SHIPMENT_ID KOLLI LINES PICKED_WEIGHT PALLETS BOTTOM_PALLETS
-- SHIPMENT-1 54.00 1 1070.280 1 1
-- SHIPMENT-2 24.00 1 471.360 1 1
-- SHIPMENT-3 12.00 1 237.960 1 1
-- SHIPMENT-4 25.00 1 102.750 1 1
-- SHIPMENT-5 3.00 1 40.650 1 1
-- SHIPMENT-6 16.00 2 316.640 1 1
-- SHIPMENT-7 60.00 1 330.000 2 2
-- SHIPMENT-8 18.00 9 125.110 1 1
-- SHIPMENT-9 3.00 2 34.340 1 1
You should at least create primary constraint on as
ALTER TABLE #dispatchPallet TABLE ADD PRIMARY KEY (PICK_PALL_NUM);
Foreign Key constraint as
ALTER TABLE #pickLog TABLE ADD foreign key (PICK_PALL_NUM) references #dispatchPallet(PICK_PALL_NUM)
Also create a unique index on
CREATE UNIQUE NONCLUSTERED INDEX idx_PALLET_PLACEMENT_notnull
ON #dispatchPallet(PALLET_PLACEMENT)
WHERE PALLET_PLACEMENT IS NOT NULL;
Your query is simple and there isn't much room to optimize. You should check that you at least have indexes on dispatchPallet by SHIPMENT_ID and on pickLog by PICK_PALL_NUM. These would be the best choices for your query:
CREATE NONCLUSTERED INDEX NCI_dispatchPallet_shipment_ID
ON dispatchPallet (SHIPMENT_ID, PICK_PALL_NUM)
INCLUDE (PALLET_PLACEMENT)
CREATE NONCLUSTERED INDEX NCI_pickLog_pick_pall_num
ON pickLog (PICK_PALL_NUM)
INCLUDE (QTY_SUF, LINE_NUM, WEIGHT_GROSS)
You should also validate if you need your COUNT to be DISTINCT or not (distinct is an expensive operation).
Last but not least, you should really check how you access the view; if you are filtering it, joining it, etc. These other conditions might generate different query plans and make your performance go down if not managed correctly (even with the right indexes!).
For starters there should be primary keys and foreign keys on these tables so that this query can do index seeks/scans (paparazzo's comment above) as opposed to full table seeks/scans.
In addition to the bigint/int, what's the purpose of the uniqueidentifier?
Good evening everyone,
I'm working on a assignment and can't figure out the following, I have two tables:
CREATE TABLE Rental (
rental_id DECIMAL(12) PRIMARY KEY,
customer_id DECIMAL(12),
movie_id DECIMAL(12),
delivery_status VARCHAR(64),
return_status VARCHAR(64));
and
CREATE TABLE Movie (
movie_id DECIMAL(12) PRIMARY KEY,
DVD_id INTEGER NOT NULL,
title VARCHAR(64) NOT NULL,
stock_number DECIMAL(12),
director_id DECIMAL(12),
genre_id DECIMAL(12),
release_date DATE NOT NULL,
restrictions VARCHAR(256) NOT NULL);
I need to do the following, list the names of all movies that are currently unavailable, rented and not yet returned. And this is my query:
SELECT Movie.movie_id, Movie.title, Movie.stock_number
FROM Movie
WHERE (Movie.movie_id, Movie.stock_number) NOT IN (
SELECT Rental.movie_id,
COUNT(Rental.return_status) AS number_of_unreturned
FROM Rental
WHERE Rental.return_status = 'Unreturned'
GROUP BY Rental.movie_id
HAVING COUNT (Rental.return_status) > 1) AND Movie.stock_number = 0;
I definitely have movies in Movie table that are not "Unreturend" but I get no rows selected all the time. Any advices or directions to think would be appreciated. Thanks!
I edited this post and added the content of the tables.
INSERT INTO Movie VALUES (1, 1, 'Amblin', 1, 1, 1, CAST('18-Dec-1968' AS DATE), 'G');
INSERT INTO Movie VALUES (2, 2, 'Duel', 2, 1, 2, CAST('13-Nov-1971' AS DATE), 'R');
INSERT INTO Movie VALUES (3, 3, 'Something Evil ', 3, 1, 3, CAST('21-Jan-1972' AS DATE), 'R');
INSERT INTO Movie VALUES (4, 4, 'The Sugarland Express ', 4, 1, 4, CAST('05-Apr-1974' AS DATE), 'PG13');
INSERT INTO Movie VALUES (5, 5, 'Jaws', 5, 1, 3, CAST('20-Jun-1975' AS DATE), 'R');
INSERT INTO Movie VALUES (6, 6, 'Close Encounters of the Third Kind', 6, 1, 5, CAST('16-Nov-1977' AS DATE), 'PG13');
INSERT INTO Movie VALUES (7, 7, ' 1941', 7, 1, 6, CAST('14-Dec-1979' AS DATE), 'G');
INSERT INTO Movie VALUES (8, 8, 'Raiders of the Lost Ark', 8, 1, 7, CAST('12-Jun-1981' AS DATE), 'PG13');
INSERT INTO Movie VALUES (9, 9, 'E.T. the Extra-Terrestrial', 9, 1, 5, CAST('11-Jun-1982' AS DATE), 'PG13');
INSERT INTO Movie VALUES (10, 10, 'Twilight Zone: The Movie', 10, 1, 3, CAST('24-Jun-1983' AS DATE), 'R');
INSERT INTO Movie VALUES (11, 11, 'Indiana Jones and the Temple of Doom', 11, 1, 7, CAST('23-May-1984' AS DATE), 'PG13');
INSERT INTO Movie VALUES (12, 12, 'The Color Purple', 12, 1, 4, CAST('18-Dec-1985' AS DATE), 'G');
INSERT INTO Movie VALUES (13, 13, 'Empire of the Sun', 13, 1, 4, CAST('25-Dec-1987' AS DATE), 'G');
INSERT INTO Movie VALUES (14, 14, 'Always', 14, 1, 4, CAST('22-Dec-1989' AS DATE), 'G');
INSERT INTO Movie VALUES (15, 15, 'Indiana Jones and the Last Crusade', 15, 1, 7, CAST('24-May-1989' AS DATE), 'G');
INSERT INTO Movie VALUES (16, 16, 'Hook', 16, 1, 8, CAST('11-Dec-1991' AS DATE), 'G');
INSERT INTO Movie VALUES (17, 17, 'Jurassic Park ', 17, 1, 5, CAST('11-Jun-1993' AS DATE), 'PG13');
INSERT INTO Movie VALUES (18, 18, 'Schindler''s List', 18, 1, 4, CAST('15-Dec-1993' AS DATE), 'PG13');
INSERT INTO Movie VALUES (19, 19, 'The Lost World: Jurassic Park', 19, 1, 5, CAST('23-May-1997' AS DATE), 'PG13');
INSERT INTO Movie VALUES (20, 20, 'Amistad', 20, 1, 4, CAST('10-Dec-1997' AS DATE), 'PG13');
INSERT INTO Movie VALUES (21, 21, 'Saving Private Ryan', 21, 1, 4, CAST('24-Jul-1998' AS DATE), 'PG13');
INSERT INTO Movie VALUES (22, 22, 'A.I. Artificial Intelligence', 22, 1, 4, CAST('29-Jun-2001' AS DATE), 'PG13');
INSERT INTO Movie VALUES (23, 23, 'Minority Report', 23, 1, 7, CAST('21-Jun-2002' AS DATE), 'PG13');
INSERT INTO Movie VALUES (24, 24, 'Catch Me If You Can', 24, 1, 8, CAST('25-Dec-2002' AS DATE), 'PG13');
INSERT INTO Movie VALUES (25, 25, ' The Terminal', 25, 1, 4, CAST('18-Jun-2004' AS DATE), 'G');
INSERT INTO Movie VALUES (26, 26, 'War of the Worlds', 26, 1, 5, CAST('29-Jun-2005' AS DATE), 'PG13');
INSERT INTO Movie VALUES (27, 27, 'Munich', 27, 1, 4, CAST('23-Dec-2005' AS DATE), 'PG13');
INSERT INTO Movie VALUES (28, 28, 'Indiana Jones and the Kingdom of the Crystal Skull', 28, 1, 7, CAST('22-May-2008' AS DATE), 'PG13');
INSERT INTO Movie VALUES (29, 29, 'The Adventures of Tintin', 28, 1, 7, CAST('21-Dec-2011' AS DATE), 'PG13');
INSERT INTO Movie VALUES (30, 30, 'War Horse', 30, 1, 4, CAST('25-Dec-2011' AS DATE), 'PG13');
INSERT INTO Movie VALUES (31, 31, 'Lincoln', 31, 1, 4, CAST('09-Nov-2012' AS DATE), 'PG13');
INSERT INTO Movie VALUES (32, 32, 'Bridge of Spies', 32, 1, 4, CAST('16-Oct-2015' AS DATE), 'PG13');
INSERT INTO Movie VALUES (33, 33, 'The BFG', 33, 1, 8, CAST('01-Jul-2016' AS DATE), 'PG13');
INSERT INTO Movie VALUES (34, 34, 'Praying with Anger', 34, 2, 5, CAST('12-Sep-1992' AS DATE), 'PG13');
INSERT INTO Movie VALUES (35, 35, 'Wide Awake', 35, 2, 4, CAST('20-Mar-1998' AS DATE), 'G');
INSERT INTO Movie VALUES (36, 36, 'The Sixth Sense', 36, 2, 2, CAST('06-Aug-1999' AS DATE), 'PG13');
INSERT INTO Movie VALUES (37, 37, 'Unbreakable', 37, 2, 2, CAST('22-Nov-2000' AS DATE), 'PG13');
INSERT INTO Movie VALUES (38, 38, 'Signs', 38, 2, 2, CAST('02-Aug-2002' AS DATE), 'PG13');
INSERT INTO Movie VALUES (39, 39, 'The Village', 39, 2, 2, CAST('30-Jul-2004' AS DATE), 'PG13');
INSERT INTO Movie VALUES (40, 40, 'Lady in the Water', 40, 2, 8, CAST('21-Jul-2006' AS DATE), 'PG13');
INSERT INTO Movie VALUES (41, 41, 'The Happening', 41, 2, 2, CAST('13-Jun-2008' AS DATE), 'R');
INSERT INTO Movie VALUES (42, 42, 'The Last Airbender', 42, 2, 7, CAST('02-Jul-2010' AS DATE), 'G');
INSERT INTO Movie VALUES (43, 43, 'After Earth', 43, 2, 7, CAST('31-May-2013' AS DATE), 'G');
INSERT INTO Movie VALUES (44, 44, 'The Visit', 44, 2, 3, CAST('11-Sep-2015' AS DATE), 'R');
INSERT INTO Movie VALUES (45, 45, 'Split', 45, 2, 2, CAST('20-Jan-2017' AS DATE), 'PG13');
and
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 1, 1, 'Delivered', 'Unreturned');
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 2, 1, 'Delivered', 'Unreturned');
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 3, 6, 'Delivered', 'Unreturned');
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 4, 7, 'Delivered', 'Unreturned');
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 2, 2, 'Delivered', 'Unreturned');
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 2, 37, 'Delivered', 'Unreturned');
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 5, 1, 'Delivered', 'Unreturned');
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 5, 24, 'Delivered', 'Unreturned');
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 5, 3, 'Delivered', 'Unreturned');
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 6, 13, 'Delivered', 'Unreturned');
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 6, 2, 'Delivered', 'Unreturned');
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 6, 8, 'Delivered', 'Unreturned');
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 6, 1, 'Delivered', 'Unreturned');
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 5, 2, 'Delivered', 'Unreturned');
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 5, 3, 'Delivered', 'Unreturned');
INSERT INTO Rental VALUES (sequence_rental.NEXTVAL, 3, 27, 'Delivered', 'Returned');
Sorry if that is a too long post.
I don't want to write the code since you are a student. I'll give some direction though. In your where clause you're comparing (movie.movie_id = rental.movie_id) and (movie.stock_number = count(rental.return_status). Comparing the stock_number to the count of returns is incorrect.
When returning columns from multiple tables, use a join. The in statement does a comparison. Count is not being returned.
Join movies and the "in" subquery on movie_id. Create an alias on the subquery so you can join it.
Add the count column to the topmost outer select
Please try, if this logic is correct, I did not quite understand column naming. You might change last row (having) to correct it.
SELECT
m.movie_id, m.title, m.stock_number -- Getting movie id, movie title, stock number
FROM Movie m -- from movie table
JOIN rental r
ON (m.movie_id = r.movie_id) -- joining rental table in movie_id
WHERE
r.return_status = 'Unreturned' -- where return_status is unreturned
GROUP BY
m.movie_id, m.title, m.stock_number -- grouping_by (same as select)
HAVING
SUM(r.movie_id) > m.stock_number; -- restricting group by quantity
To resolve the query try first to break it down in the components you need.
In this case you need to compare the number of rented movies against the stock of movies.
So write 2 separte queries:
1 - One that will provide the movie id and the number to movies in stock.
2 - Another for the movie id and the number of rentals. For this one you have to count the unretured.
After you have the two queries, you can use them as subqueries of a higer level query that treats each or these queries as a table joined by the common id field.
And add awhere clause comparing the stock with the counted field.
Example:
Table A: id, name, age
Table B: table_b_id, table_a_id, telephone, address
Query 1: select id, name, age from A
Query 2: select table_a_id, telephone, address from B
select Q1.id, Q1.name, Q1.age, Q2telephone, Q2.address
from
(select A.id, A.name, A.age from A) Q1,
(select B.table_a_id, B.telephone, B.address from B) Q2
where
Q1.id = Q2.table_a_id
Trying to make a database that allows for a course to have several sections, and a section to have several events/periods as to when they meet. Everything is linked properly, however I am having a problem with a PostgreSQL error which I realize is telling me that I need UNIQUE attributes in the "Sections" and "ClassEvent" Tables, but I can't have them be UNIQUE because it is information that should/can be repeated.
DROP TABLE IF EXISTS Stats;
DROP TABLE IF EXISTS ClassEvent;
DROP TABLE IF EXISTS Enrollment;
DROP TABLE IF EXISTS DegreeReq;
DROP TABLE IF EXISTS DegreeInstance;
DROP TABLE IF EXISTS Sections;
DROP TABLE IF EXISTS Students;
DROP TABLE IF EXISTS Degrees;
DROP TABLE IF EXISTS Professors;
DROP TABLE IF EXISTS People;
DROP TABLE IF EXISTS Courses;
-- HOLDS A SPECIFIC COURSE WITHOUT THE INSTANCES OF THE CLASS --
CREATE TABLE Courses (
courseID SERIAL UNIQUE NOT NULL,
department VARCHAR(4) NOT NULL,
courseNumber VARCHAR(5) NOT NULL,
courseName TEXT UNIQUE NOT NULL,
credits INT NOT NULL,
PRIMARY KEY(courseID)
);
-- PEOPLE SUPERTYPE --
CREATE TABLE People (
pid SERIAL UNIQUE NOT NULL,
fname TEXT NOT NULL,
lname TEXT NOT NULL,
PRIMARY KEY(pid)
);
-- HOLDS THE DIFFERENT PROFESSORS TEACHING AT THE SCHOOL --
-- SUBTYPE OF PEOPLE --
CREATE TABLE Professors (
professorID SERIAL UNIQUE NOT NULL,
status TEXT NOT NULL,
CHECK(status = 'Full-Time' OR status = 'Part-time'),
PRIMARY KEY(professorID)
);
-- HOLDS THE SPECIFIC INSTANCES OF THE CLASS DEPENDING ON THE YEAR AND TERM --
CREATE TABLE Sections (
crn INT UNIQUE NOT NULL,
courseID SERIAL REFERENCES Courses(courseID) NOT NULL,
year INT NOT NULL,
term TEXT NOT NULL,
sectionNumber INT NOT NULL,
startDate DATE NOT NULL,
endDate DATE NOT NULL,
professorID INT REFERENCES Professors(professorID) UNIQUE NOT NULL,
PRIMARY KEY(crn, courseID)
);
-- HOLDS THE EVENT OF THE CLASS --
-- A CLASS MAY HAVE DIFFERENT DAYS ON WHICH --
-- THEY MEET ON, SO THIS ALLOWS A CERTAIN --
-- SECTION TO HAVE SEVERAL DAYS WITHOUT CONFLICT --
CREATE TABLE ClassEvent (
crn INT REFERENCES Sections(crn) NOT NULL,
year INT REFERENCES Sections(year) NOT NULL,
term TEXT REFERENCES Sections(term) NOT NULL,
professorID INT REFERENCES Professors(professorID) NOT NULL,
day TEXT,
startTime TIME,
endTime TIME,
location TEXT,
campus TEXT,
CHECK(day = 'Monday' OR day = 'Tuesday' OR day = 'Wednesday' OR day = 'Thursday' OR day = 'Friday' OR day = 'Saturday' OR day = 'Sunday' OR day = NULL),
PRIMARY KEY(crn, year, term)
);
-- HOLDS THE STUDENTS THAT WILL BE TAKING THE CLASSES --
-- SUBTYPE OF PEOPLE --
CREATE TABLE Students (
studentID INT REFERENCES People(pid) UNIQUE NOT NULL,
studentName TEXT NOT NULL,
gradYear DATE UNIQUE NOT NULL,
PRIMARY KEY(studentID)
);
-- HOLDS A CLASS RECORD FOR STUDENTS (AND POSSIBLY PROFESSORS) --
CREATE TABLE Enrollment (
studentID INT REFERENCES Students(studentID) UNIQUE NOT NULL,
crn INT REFERENCES Sections(crn) NOT NULL,
grade TEXT NOT NULL,
PRIMARY KEY(studentID, crn)
);
-- HOLDS THE DIFFERENT DEGREES THAT CAN BE ATTAINED AT THE COLLEGE/UNIVERSITY --
CREATE TABLE Degrees (
degreeID SERIAL UNIQUE NOT NULL,
degreeName TEXT NOT NULL,
degreeType TEXT NOT NULL,
degDepartment VARCHAR(4) NOT NULL,
CHECK(degreeType = 'Major' OR degreeType = 'Minor' OR degreeType = 'Masters'),
PRIMARY KEY(degreeID)
);
-- HOLDS THE CLASSES THAT WILL MAKE UP A DEGREE --
CREATE TABLE DegreeReq (
degreeID INT REFERENCES Degrees(degreeID) UNIQUE NOT NULL,
courseID INT REFERENCES Courses(courseID) UNIQUE NOT NULL,
PRIMARY KEY(degreeID, courseID)
);
-- HOLDS THE INSTANCE OF A DEGREE FOR A CERTAIN STUDENT --
-- FOR EXAMPLE: A STUDENT CAN HAVE A MAJOR AND A MINOR --
-- SO HE/SHE CAN STORE THEM SEPARATELY --
CREATE TABLE DegreeInstance (
degreeID INT REFERENCES Degrees(degreeID) UNIQUE NOT NULL,
studentID INT REFERENCES Students(studentID) UNIQUE NOT NULL,
startDate DATE NOT NULL,
endDate DATE NOT NULL,
creditsRequired INT NOT NULL,
PRIMARY KEY(degreeID, studentID)
);
-- HOLDS ALL THE RATE MY PROFESSOR STATS --
CREATE TABLE Stats (
professorID INT REFERENCES Professors(professorID) UNIQUE NOT NULL,
dateSubmitted TIMESTAMP UNIQUE NOT NULL,
rating FLOAT NOT NULL,
helpfulness FLOAT NOT NULL,
clarity FLOAT NOT NULL,
easiness FLOAT NOT NULL,
PRIMARY KEY(professorID, dateSubmitted)
);
INSERT INTO Courses(department, courseNumber, courseName, credits)
VALUES
('CMPT', '120L', 'Intro to Programming', 4),
('CMPT', '220L', 'Software Development I', 4),
('CMPT', '221L', 'Software Development II', 4),
('CMPT', '230L', 'Software Systems + Analysis', 4),
('CMPT', '306N', 'Data Communications', 4),
('CMPT', '308L', 'Database Management', 4),
('CMPT', '307N', 'Internetworking', 4),
('CMPT', '330L', 'System Design', 4),
('CMPT', '422L', 'Computer Organization and Architecture', 4),
('CMPT', '435L', 'Algorithm Analysis and Design', 4),
('CMPT', '424L', 'Operating Systems', 4),
('CMPT', '432L', 'Design of Compilers', 4),
('CMPT', '331L', 'Theory of Programming Languages', 4),
('CMPT', '440L', 'Formal Languages and Computability', 4),
('CMPT', '333L', 'Language Study', 4),
('CMPT', '475L', 'CS Project I', 4),
('CMPT', '476L', 'CS Project II', 4),
('BUS', '100N', 'Intro to Business & Management', 4),
('MATH', '130L', 'Intro to Statistics I', 3),
('MATH', '241L', 'Calculus I', 4),
('MATH', '242L', 'Calculus II', 4),
('FYS', '101L', 'First Year Seminar', 4),
('ENG', '120L', 'Writing for College', 3),
('PHIL', '101L', 'Philosophical Perspectives', 3),
('MUS', '120L', 'Theory of Music I', 3),
('ECON', '103L', 'Principles of Microeconomics', 3),
('ECON', '104L', 'Principles of Macroeconomics', 3),
('MATH', '343L', 'Calculus III', 4),
('MATH', '310L', 'Intro to Mathematics Reasoning', 3),
('CMPT', '416N', 'Intro to Cybersecurity', 4),
('CMPT', '446N', 'Computer Graphics', 4),
('CMPT', '404L', 'Artificial Intelligence', 4),
('CMPT', '305L', 'Technology, Ethics and Society', 3),
('CMPT', '192N', 'Competitive Programming', 1);
INSERT INTO People(fname, lname)
VALUES
('Marcos', 'Barbieri'),
('James', 'Crowley'),
('Kaylee', 'Pope'),
('Pablo', 'Rivas'),
('Matthew', 'Johnson'),
('Anne', 'Matheus'),
('Joe', 'Smith'),
('Mike', 'Emmet'),
('Michael', 'Jordan'),
('Alan', 'Labouseur');
INSERT INTO Professors(professorID, status)
VALUES
(4, 'Full-Time'),
(5, 'Full-Time'),
(6, 'Full-Time'),
(7, 'Full-Time'),
(10, 'Full-Time');
INSERT INTO Sections(crn, courseID, year, term, sectionNumber, startDate, endDate, professorID)
VALUES
(11111, 1, 2016, 'Fall', 111, '2016-08-29', '2016-12-15', 4),
(11112, 1, 2016, 'Fall', 112, '2016-08-29', '2016-12-15', 4),
(11113, 1, 2016, 'Fall', 113, '2016-08-29', '2016-12-15', 4),
(11121, 2, 2016, 'Fall', 111, '2016-08-29', '2016-12-15', 5),
(11122, 2, 2016, 'Fall', 112, '2016-08-29', '2016-12-15', 5),
(11123, 2, 2016, 'Fall', 113, '2016-08-29', '2016-12-15', 5),
(11211, 3, 2016, 'Fall', 111, '2016-08-29', '2016-12-15', 6),
(11212, 3, 2016, 'Fall', 112, '2016-08-29', '2016-12-15', 6),
(11213, 3, 2016, 'Fall', 113, '2016-08-29', '2016-12-15', 6),
(11214, 4, 2016, 'Fall', 111, '2016-08-29', '2016-12-15', 7),
(11215, 4, 2016, 'Fall', 112, '2016-08-29', '2016-12-15', 7),
(11216, 5, 2016, 'Fall', 111, '2016-08-29', '2016-12-15', 10),
(11217, 6, 2016, 'Fall', 111, '2016-08-29', '2016-12-15', 10),
(11118, 6, 2016, 'Fall', 112, '2016-08-29', '2016-12-15', 4),
(11119, 6, 2016, 'Fall', 113, '2016-08-29', '2016-12-15', 5),
(11120, 6, 2016, 'Fall', 114, '2016-08-29', '2016-12-15', 4),
(11200, 7, 2016, 'Fall', 111, '2016-08-29', '2016-12-15', 5),
(11201, 7, 2016, 'Fall', 112, '2016-08-29', '2016-12-15', 5),
(11202, 8, 2016, 'Fall', 111, '2016-08-29', '2016-12-15', 10),
(11203, 9, 2016, 'Fall', 111, '2016-08-29', '2016-12-15', 10),
(11204, 10, 2016, 'Fall', 111, '2016-08-29', '2016-12-15', 6),
(11205, 10, 2016, 'Fall', 112, '2016-08-29', '2016-12-15', 6),
(11206, 10, 2016, 'Fall', 113, '2016-08-29', '2016-12-15', 6),
(11207, 10, 2016, 'Fall', 114, '2016-08-29', '2016-12-15', 6),
(11208, 11, 2016, 'Fall', 111, '2016-08-29', '2016-12-15', 4),
(11209, 11, 2016, 'Fall', 112, '2016-08-29', '2016-12-15', 4),
(11222, 12, 2016, 'Fall', 111, '2016-08-29', '2016-12-15', 4),
(11333, 12, 2016, 'Fall', 112, '2016-08-29', '2016-12-15', 5),
(11445, 12, 2016, 'Fall', 113, '2016-08-29', '2016-12-15', 7),
(11111, 12, 2016, 'Fall', 111, '2016-08-29', '2016-12-15', 4),
(11678, 13, 2016, 'Fall', 111, '2016-08-29', '2016-12-15', 10),
(11679, 13, 2016, 'Fall', 112, '2016-08-29', '2016-12-15', 4);
SELECT * FROM Sections;
I try to do this and I get the following error:
ERROR: there is no unique constraint matching given keys for referenced table "sections"
********** Error **********
ERROR: there is no unique constraint matching given keys for referenced table "sections"
SQL state: 42830
You do not need to have year and term as foreign keys in the class events table. This information is redundant as it can be looked up in sections table via the crn. I suggest changing your create statement for ClassEvents as follows:
CREATE TABLE ClassEvent (
crn INT REFERENCES Sections(crn) NOT NULL,
professorID INT REFERENCES Professors(professorID) NOT NULL,
day TEXT NOT NULL,
startTime TIME NOT NULL,
endTime TIME,
location TEXT,
campus TEXT,
CHECK(day = 'Monday' OR day = 'Tuesday' OR day = 'Wednesday' OR day = 'Thursday' OR day = 'Friday' OR day = 'Saturday' OR day = 'Sunday' OR day = NULL),
PRIMARY KEY(crn, day, startTime,professorID)
);
I have changed primary key to be a combination of course,date/time and professor - as a professor cannot be teaching more than course on any given point in time.