Using count in a Subquery - mysql

Im currently learning about sub querys in mysql and just want to clarify if im on the right track. The below code does bring a result but im unsure if im doing it correctly. The question is
"Find a code and company name of all customers who submitted at least one order in April 1997 using an IN statement ."
SELECT CUSTOMER_CODE, COMPANY_NAME
FROM CUSTOMER
WHERE CUSTOMER_CODE IN (SELECT CUSTOMER_CODE
FROM ORDERS
WHERE ORDER_DATE BETWEEN '1997-04-01' AND '1997-04-30'
GROUP BY CUSTOMER_CODE )
I went through the values that are inserted into the tables and it just doesnt seem to be correct even though a result is produced.
(Side note, is using a EXIST clause the same as a IN clause, but instead of WHERE CUSTOMER_CODE IN it is WHERE EXISTS ?
I tried this
SELECT CUSTOMER_CODE, COMPANY_NAME
FROM CUSTOMER
WHERE NOT EXISTS (SELECT CUSTOMER_CODE
FROM ORDERS
WHERE ORDER_DATE BETWEEN '1997-04-01' AND '1997-04-30'
GROUP BY CUSTOMER_CODE );
these are the two talbes im using
CREATE TABLE CUSTOMER
(
CUSTOMER_CODE VARCHAR(5) NOT NULL,
COMPANY_NAME VARCHAR(40) NOT NULL,
CONTACT_NAME VARCHAR(30),
CONTACT_TITLE VARCHAR(30),
ADDRESS VARCHAR(60),
CITY VARCHAR(15),
REGION VARCHAR(15),
POSTAL_CODE VARCHAR(10),
COUNTRY VARCHAR(15),
PHONE VARCHAR(24),
FAX VARCHAR(24),
CONSTRAINT PK_CUSTOMER PRIMARY KEY (CUSTOMER_CODE)
);
CREATE TABLE ORDERS
(
ORDER_ID DECIMAL(9) NOT NULL,
CUSTOMER_CODE VARCHAR(5) NOT NULL,
EMPLOYEE_ID DECIMAL(9) NOT NULL,
ORDER_DATE DATE NOT NULL,
REQUIRED_DATE DATE,
SHIPPED_DATE DATE,
SHIP_VIA VARCHAR(40),
FREIGHT DECIMAL(10,2) DEFAULT 0,
SHIP_NAME VARCHAR(40),
SHIP_ADDRESS VARCHAR(60),
SHIP_CITY VARCHAR(15),
SHIP_REGION VARCHAR(15),
SHIP_POSTAL_CODE VARCHAR(10),
SHIP_COUNTRY VARCHAR(15),
CONSTRAINT PK_ORDERS PRIMARY KEY (ORDER_ID),
CONSTRAINT FK_CUSTOMER_CODE FOREIGN KEY (CUSTOMER_CODE) REFERENCES CUSTOMER(CUSTOMER_CODE),
CONSTRAINT FK_EMPLOYEE_ID FOREIGN KEY (EMPLOYEE_ID) REFERENCES EMPLOYEE(EMPLOYEE_ID),
CONSTRAINT FK_SHIP_VIA FOREIGN KEY (SHIP_VIA) REFERENCES SHIPPER(COMPANY_NAME)
);
but i recieve an empty set
Thankyou all for your time

instead of a IN clause you could use a INNER JOIN based on the same subquery ..
usually this perform better that a In clause
SELECT CUSTOMER_CODE, COMPANY_NAME
FROM CUSTOMER
INNER JOIN (
SELECT DISTINCT CUSTOMER_CODE
FROM ORDERS
WHERE ORDER_DATE BETWEEN '1997-04-01' AND '1997-04-30'
) t on t.CUSTOMER_CODE = CUSTOMER.CUSTOMER_CODE
You should not use group by for when you don't use aggregation function (this don't work by default in most recent version of mysql)
use DISTINCT if you need only distinct result

You must use EXISTS instead of NOT EXISTS:
SELECT c.CUSTOMER_CODE, c.COMPANY_NAME
FROM CUSTOMER c
WHERE EXISTS (
SELECT CUSTOMER_CODE FROM ORDERS
WHERE
CUSTOMER_CODE = c.CUSTOMER_CODE
AND
ORDER_DATE BETWEEN '1997-04-01' AND '1997-04-30'
);
You can also check about the ORDER_DATE with this:
YEAR(ORDER_DATE) = 1997 AND MONTH(ORDER_DATE) = 4
You can also do it with IN:
SELECT CUSTOMER_CODE, COMPANY_NAME
FROM CUSTOMER
WHERE CUSTOMER_CODE IN (
SELECT CUSTOMER_CODE FROM ORDERS
WHERE YEAR(ORDER_DATE) = 1997 AND MONTH(ORDER_DATE) = 4
);
If you want to find the total number of all customers who submitted no orders:
SELECT COUNT(DISTINCT c.CUSTOMER_CODE) AS COUNTER
FROM CUSTOMER c
WHERE NOT EXISTS (
SELECT CUSTOMER_CODE FROM ORDERS
WHERE CUSTOMER_CODE = c.CUSTOMER_CODE
)

Related

How Do I create a view that shows the total number of items a customer buys from the business in April 2019 along with the total price in SQL?

I'm struggling to create a view in SQL that will the total number of items a customer buys from the business in April 2019 along with the total price.
Here are my tables.
CREATE TABLE Customer (
CustID int AUTO_INCREMENT,
Fname varchar(50) NOT NULL,
Sname varchar(50) NOT NULL,
PRIMARY KEY (CustID)
);
CREATE TABLE Transaction (
TransID int AUTO_INCREMENT,
OrderDate date NOT NULL,
ArriveDate date NOT NULL,
CustID int,
PRIMARY KEY (TransID),
FOREIGN KEY (CustID) REFERENCES Customer(CustID)
);
CREATE TABLE TransactionDetails(
TranDetID int AUTO_INCREMENT NOT NULL,
quantity int NOT NULL,
price int NOT NULL,
TransID int,
PRIMARY KEY (TranDetID),
FOREIGN KEY (TransID) REFERENCES Transaction(TransID)
);
Hope this helps. you can change the year and month using the 1st 2 lines of code
DECLARE #Year INT = 2019,
#Month NVARCHAR(15) = 'April'
SELECT C.Fname, SUM(TD.quantity) AS quantity, SUM(TD.price) AS price
FROM [Transaction] T
LEFT JOIN customer C ON C.CustID = T.CustID
LEFT JOIN TransactionDetails TD ON TD.TransID = T.TransID
WHERE DATENAME(month, OrderDate) = #Month AND DATENAME(YEAR, OrderDate) = #Year
GROUP BY C.Fname
Seems curious, but:
select td.custid, sum(quantity) as total_quantity,
sum(price) as total_price. -- perhaps "price * quantity"???
from transactions t join
transactiondetails td
using (TransID)
where t.orderdate >= '2019-04-01' and t.orderdate < '2019-05-01';
This is curious because your data model does not distinguish between products, which I would expect. It is unclear whether the price needs to be multiplied by the quantity, because you have no sample data and desired results.

Altering a Table to Add a Column thats Value is set using a UPDATE JOIN Query

Im trying to create a Column thats Value is defined through anUPDATE JOIN SET statement. The exact question that im trying to answer actually is
"Add to a relational table EMPLOYEE information about the total number of orders handled by each employee. Note, that if an employee handled no orders then for such employee the total number of orders must be set to zero. Enforce the appropriate consistency constraints on a relational table EMPLOYEE. "
ALTER TABLE EMPLOYEE
ADD TOTALNUMBER VARCHAR(40) NOT NULL;
UPDATE EMPLOYEE E JOIN ORDERS O ON(E.EMPLOYEE_ID = O.EMPLOYEE_ID)
SET E.TOTALNUMBER = E.EMPLOYEE_ID + O.ORDER_ID;
UPDATE EMPLOYEE
SET TOTALNUMBER = 0
WHERE TOTALNUMBER IS NULL;
tables being used
CREATE TABLE EMPLOYEE
(
EMPLOYEE_ID DECIMAL(9) NOT NULL,
LASTNAME VARCHAR(20) NOT NULL,
FIRSTNAME VARCHAR(10) NOT NULL,
TITLE VARCHAR(30),
TITLE_OF_COURTESY VARCHAR(25),
BIRTHDATE DATE,
HIREDATE DATE,
ADDRESS VARCHAR(60),
CITY VARCHAR(15),
REGION VARCHAR(15),
POSTAL_CODE VARCHAR(10),
COUNTRY VARCHAR(15),
HOME_PHONE VARCHAR(24),
EXTENSION VARCHAR(4),
PHOTO VARCHAR(255),
NOTES VARCHAR(2000),
REPORTS_TO DECIMAL(9),
CONSTRAINT PK_EMPLOYEE PRIMARY KEY (EMPLOYEE_ID)
);
CREATE TABLE ORDERS
(
ORDER_ID DECIMAL(9) NOT NULL,
CUSTOMER_CODE VARCHAR(5) NOT NULL,
EMPLOYEE_ID DECIMAL(9) NOT NULL,
ORDER_DATE DATE NOT NULL,
REQUIRED_DATE DATE,
SHIPPED_DATE DATE,
SHIP_VIA VARCHAR(40),
FREIGHT DECIMAL(10,2) DEFAULT 0,
SHIP_NAME VARCHAR(40),
SHIP_ADDRESS VARCHAR(60),
SHIP_CITY VARCHAR(15),
SHIP_REGION VARCHAR(15),
SHIP_POSTAL_CODE VARCHAR(10),
SHIP_COUNTRY VARCHAR(15),
CONSTRAINT PK_ORDERS PRIMARY KEY (ORDER_ID),
CONSTRAINT FK_CUSTOMER_CODE FOREIGN KEY (CUSTOMER_CODE) REFERENCES CUSTOMER(CUSTOMER_CODE),
CONSTRAINT FK_EMPLOYEE_ID FOREIGN KEY (EMPLOYEE_ID) REFERENCES EMPLOYEE(EMPLOYEE_ID),
CONSTRAINT FK_SHIP_VIA FOREIGN KEY (SHIP_VIA) REFERENCES SHIPPER(COMPANY_NAME)
);
Im unsure of what the exact result should be but i recieve a total of 9 rows with values ranging between 252 to 296. It doesnt seem to odd that an employee would deal with this many Orders but it seems to be too small of a list.
I don't recommend your current approach, and the best way to determine the number of orders per employees is to just aggregate and join, without storing this number in the actual employee table. That being said, if you want to proceed this way, then consider using this update query:
UPDATE EMPLOYEE e
LEFT JOIN
(
SELECT EMPLOYEE_ID, COUNT(*) AS num_orders
FROM ORDERS
GROUP BY EMPLOYEE_ID
) o
ON e.EMPLOYEE_ID = o.EMPLOYEE_ID
SET TOTALNUMBER = COALESCE(o.num_orders, 0);
Or, you could use:
SET TOTALNUMBER = o.num_orders;
and then use your second update to zero-out the employee totals which had no orders at all:
UPDATE EMPLOYEE
SET TOTALNUMBER = 0
WHERE TOTALNUMBER IS NULL;
But note that this would require that the TOTALNUMBER columns is not nullable. So you would need to remove the NOT NULL constraint.

MySQL: Implicit Join with conditions: What kind of statement would I need for duplicate removal?

I'm working on JOIN statements (implicit) and I've set up the code to join without much of a hitch, and when the code runs I get quite a few duplicates per person. I was wondering what kind of statement I should use to only show one of each person?
Select Statement
SELECT CONCAT(customers.customer_first_name, ' ', customers.customer_last_name) as 'Customer',
orders.order_date as 'Order Date', customers.customer_zip as 'Zipcode'
FROM customers, orders, order_details
WHERE order_details.item_id = 10
ORDER BY CONCAT(customers.customer_first_name, ' ', customers.customer_last_name) ASC;
If you need other parts of the code, they are readily available.
Create Table/Insert Statements:
/*Create Tables*/
CREATE TABLE customers
(
customer_id INT,
customer_first_name VARCHAR(20),
customer_last_name VARCHAR(20) NOT NULL,
customer_address VARCHAR(50) NOT NULL,
customer_city VARCHAR(20) NOT NULL,
customer_state CHAR(2) NOT NULL,
customer_zip CHAR(5) NOT NULL,
customer_phone CHAR(10) NOT NULL,
customer_fax CHAR(10),
CONSTRAINT customers_pk
PRIMARY KEY (customer_id)
);
CREATE TABLE artists
(
artist_id INT NOT NULL,
artist_name VARCHAR(30),
CONSTRAINT artist_pk
PRIMARY KEY (artist_id)
);
CREATE TABLE items
(
item_id INT NOT NULL,
title VARCHAR(50) NOT NULL,
artist_id INT NOT NULL,
unit_price DECIMAL(9,2) NOT NULL,
CONSTRAINT items_pk
PRIMARY KEY (item_id),
CONSTRAINT items_fk_artists
FOREIGN KEY (artist_id) REFERENCES artists (artist_id)
);
CREATE TABLE employees
(
employee_id INT NOT NULL,
last_name VARCHAR(20) NOT NULL,
first_name VARCHAR(20) NOT NULL,
manager_id INT,
CONSTRAINT employees_pk
PRIMARY KEY (employee_id),
CONSTRAINT emp_fk_mgr FOREIGN KEY (manager_id) REFERENCES employees(employee_id)
);
CREATE TABLE orders
(
order_id INT NOT NULL,
customer_id INT NOT NULL,
order_date DATE NOT NULL,
shipped_date DATE,
employee_id INT,
CONSTRAINT orders_pk
PRIMARY KEY (order_id),
CONSTRAINT orders_fk_customers
FOREIGN KEY (customer_id) REFERENCES customers (customer_id),
CONSTRAINT orders_fk_employees
FOREIGN KEY (employee_id) REFERENCES employees (employee_id)
);
CREATE TABLE order_details
(
order_id INT NOT NULL,
item_id INT NOT NULL,
order_qty INT NOT NULL,
CONSTRAINT order_details_pk
PRIMARY KEY (order_id, item_id),
CONSTRAINT order_details_fk_orders
FOREIGN KEY (order_id)
REFERENCES orders (order_id),
CONSTRAINT order_details_fk_items
FOREIGN KEY (item_id)
REFERENCES items (item_id)
);
/*Insert Statements*/
INSERT INTO customers VALUES
(1,'Korah','Blanca','1555 W Lane Ave','Columbus','OH','43221','6145554435','6145553928'),
(2,'Yash','Randall','11 E Rancho Madera Rd','Madison','WI','53707','2095551205','2095552262'),
(3,'Johnathon','Millerton','60 Madison Ave','New York','NY','10010','2125554800',NULL),
(4,'Mikayla','Davis','2021 K Street Nw','Washington','DC','20006','2025555561',NULL),
(5,'Kendall','Mayte','4775 E Miami River Rd','Cleves','OH','45002','5135553043',NULL),
(6,'Kaitlin','Hostlery','3250 Spring Grove Ave','Cincinnati','OH','45225','8005551957','8005552826'),
(7,'Derek','Chaddick','9022 E Merchant Wy','Fairfield','IA','52556','5155556130',NULL),
(8,'Deborah','Davis','415 E Olive Ave','Fresno','CA','93728','5595558060',NULL),
(9,'Karina','Lacy','882 W Easton Wy','Los Angeles','CA','90084','8005557000',NULL),
(10,'Kurt','Nickalus','28210N Avenue Stanford','Valencia','CA','91355','8055550584','055556689'),
(11,'Kelsey','Eulalia','7833 N Ridge Rd','Sacramento','CA','95887','2095557500','2095551302'),
(12,'Anders','Rohansen','12345 E 67th Ave NW','Takoma Park','MD','24512','3385556772',NULL),
(13,'Thalia','Neftaly','2508 W Shaw Ave','Fresno','CA','93711','5595556245',NULL),
(14,'Gonzalo','Keeton','12 Daniel Road','Fairfield','NJ','07004','2015559742',NULL),
(15,'Ania','Irvin','1099 N Farcourt St','Orange','CA','92807','7145559000',NULL),
(16,'Dakota','Baylee','1033 NSycamore Ave.','Los Angeles','CA','90038','2135554322',NULL),
(17,'Samuel','Jacobsen','3433 E Widget Ave','Palo Alto','CA','92711','4155553434',NULL),
(18,'Justin','Javen','828 S Broadway','Tarrytown','NY','10591','8005550037',NULL),
(19,'Kyle','Marissa','789 E Mercy Ave','Phoenix','AZ','85038','9475553900',NULL),
(20,'Erick','Kaleigh','Five Lakepointe Plaza, Ste 500','Charlotte','NC','28217','7045553500',NULL),
(21,'Marvin','Quintin','2677 Industrial Circle Dr','Columbus','OH','43260','6145558600','6145557580'),
(22,'Rashad','Holbrooke','3467 W Shaw Ave #103','Fresno','CA','93711','5595558625','5595558495'),
(23,'Trisha','Anum','627 Aviation Way','Manhatttan Beach','CA','90266','3105552732',NULL),
(24,'Julian','Carson','372 San Quentin','San Francisco','CA','94161','6175550700',NULL),
(25,'Kirsten','Story','2401 Wisconsin Ave NW','Washington','DC','20559','2065559115',NULL);
INSERT INTO artists(artist_id,artist_name) VALUES
(10,'Umani'),
(11,'The Ubernerds'),
(12,'No Rest For The Weary'),
(13,'Burt Ruggles'),
(14,'Sewed the Vest Pocket'),
(15,'Jess & Odie'),
(16,'Onn & Onn');
INSERT INTO items (item_id,title,artist_id,unit_price) VALUES
(1,'Umami In Concert',10,17.95),
(2,'Race Car Sounds',11,13),
(3,'No Rest For The Weary',12,16.95),
(4,'More Songs About Structures and Comestibles',12,17.95),
(5,'On The Road With Burt Ruggles',13,17.5),
(6,'No Fixed Address',14,16.95),
(7,'Rude Noises',15,13),
(8,'Burt Ruggles: An Intimate Portrait',13,17.95),
(9,'Zone Out With Umami',10,16.95),
(10,'Etcetera',16,17);
INSERT INTO employees VALUES
(1,'Smith','Cindy',null),
(2,'Jones','Elmer',1),
(3,'Simonian','Ralph',2),
(9,'Locario','Paulo',1),
(8,'Leary','Rhea',9),
(4,'Hernandez','Olivia',9),
(5,'Aaronsen','Robert',4),
(6,'Watson','Denise',8),
(7,'Hardy','Thomas',2);
INSERT INTO orders VALUES
(19,1,'2012-10-23','2012-10-28',6),
(29,8,'2012-11-05','2012-11-11',6),
(32,11,'2012-11-10','2012-11-13',NULL),
(45,2,'2012-11-25','2012-11-30',NULL),
(70,10,'2012-12-28','2013-01-07',5),
(89,22,'2013-01-20','2013-01-22',7),
(97,20,'2013-01-29','2013-02-02',5),
(118,3,'2013-02-24','2013-02-28',7),
(144,17,'2013-03-21','2013-03-29',NULL),
(158,9,'2013-04-04','2013-04-20',NULL),
(165,14,'2013-04-11','2013-04-13',NULL),
(180,24,'2013-04-25','2013-05-30',NULL),
(231,15,'2013-06-14','2013-06-22',NULL),
(242,23,'2013-06-24','2013-07-06',3),
(264,9,'2013-07-15','2013-07-18',6),
(298,18,'2013-08-18','2013-09-22',3),
(321,2,'2013-09-09','2013-10-05',6),
(381,7,'2013-11-08','2013-11-16',7),
(413,17,'2013-12-05','2014-01-11',7),
(442,5,'2013-12-28','2014-01-03',5),
(479,1,'2014-01-30','2014-03-03',3),
(491,16,'2014-02-08','2014-02-14',5),
(523,3,'2014-03-07','2014-03-15',3),
(548,2,'2014-03-22','2014-04-18',NULL),
(550,17,'2014-03-23','2014-04-03',NULL),
(601,16,'2014-04-21','2014-04-27',NULL),
(607,20,'2014-04-25','2014-05-04',NULL),
(624,2,'2014-05-04','2014-05-09',NULL),
(627,17,'2014-05-05','2014-05-10',NULL),
(630,20,'2014-05-08','2014-05-18',7),
(651,12,'2014-05-19','2014-06-02',7),
(658,12,'2014-05-23','2014-06-02',7),
(687,17,'2014-06-05','2014-06-08',NULL),
(693,9,'2014-06-07','2014-06-19',NULL),
(703,19,'2014-06-12','2014-06-19',7),
(778,13,'2014-07-12','2014-07-21',7),
(796,17,'2014-07-19','2014-07-26',5),
(800,19,'2014-07-21','2014-07-28',NULL),
(802,2,'2014-07-21','2014-07-31',NULL),
(824,1,'2014-08-01',NULL,NULL),
(827,18,'2014-08-02',NULL,NULL),
(829,9,'2014-08-02',NULL,NULL);
INSERT INTO order_details VALUES
(381,1,1),
(601,9,1),
(442,1,1),
(523,9,1),
(630,5,1),
(778,1,1),
(693,10,1),
(118,1,1),
(264,7,1),
(607,10,1),
(624,7,1),
(658,1,1),
(800,5,1),
(158,3,1),
(321,10,1),
(687,6,1),
(827,6,1),
(144,3,1),
(479,1,2),
(630,6,2),
(796,5,1),
(97,4,1),
(601,5,1),
(800,1,1),
(29,10,1),
(70,1,1),
(165,4,1),
(180,4,1),
(231,10,1),
(413,10,1),
(491,6,1),
(607,3,1),
(651,3,1),
(703,4,1),
(802,3,1),
(824,7,2),
(829,1,1),
(550,4,1),
(796,7,1),
(693,6,1),
(29,3,1),
(32,7,1),
(242,1,1),
(298,1,1),
(479,4,1),
(548,9,1),
(627,9,1),
(778,3,1),
(19,5,1),
(89,4,1),
(242,6,1),
(264,4,1),
(550,1,1),
(693,7,3),
(824,3,1),
(829,5,1),
(829,9,1);
You have a Descartes product, not a join. You could use the distinct keyword or you could do a group by, but it seems you really need a join instead. I am writing something like that for you, but since I do not know your table structure, I will be guessing the columns:
SELECT CONCAT(customers.customer_first_name, ' ', customers.customer_last_name) as 'Customer',
orders.order_date as 'Order Date', customers.customer_zip as 'Zipcode'
FROM order_details
join orders
on order_details.order_id = orders.order_id and order_details.item_id = 10
join customers
on orders.customer_id = customers.customer_id
ORDER BY CONCAT(customers.customer_first_name, ' ', customers.customer_last_name) ASC;
Naturally, there is no guarantee there will be a single record per customer, since we, at least lacking information cannot assume that there are no customers who have multiple orders, each having an order detail with item_id = 10
See Explicit vs implicit SQL joins ... right now you are likely getting a Cartesian product. Sorry this isn't in comments ... new user, score isn't high enough to comment yet.
If you don't want to use the JOIN keyword you can add the key columns on whick the tables are related to the WHERE clause like this:
SELECT CONCAT(customers.customer_first_name, ' ', customers.customer_last_name) as 'Customer',
orders.order_date as 'Order Date', customers.customer_zip as 'Zipcode'
FROM customers, orders, order_details
WHERE order_details.item_id = 10
AND orders.customer_id = customers.customer_id
AND order_details.order_id = orders.order_id
ORDER BY CONCAT(customers.customer_first_name, ' ', customers.customer_last_name) ASC;

How do I extract results after joining multiple tables in the following schema?

I've used the following commands for creating the tables.
CREATE TABLE Customer(
custid int NOT NULL AUTO_INCREMENT,
fname varchar(30) NOT NULL,
lname varchar(30) NOT NULL,
mno varchar(10),
password varchar(30),
PRIMARY KEY (custid)
);
CREATE TABLE Employee(
empid int NOT NULL,
fname varchar(30) NOT NULL,
lname varchar(30) NOT NULL,
mno varchar(10),
password varchar(30),
PRIMARY KEY (empid)
);
CREATE TABLE Address(
id int NOT NULL,
street varchar(30),
doorno varchar(30),
city varchar(30),
statee varchar(30),
zip varchar(5),
county varchar(30) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES Customer (custid)
);
CREATE TABLE EmpAddress(
id int NOT NULL,
street varchar(30),
doorno varchar(30),
city varchar(30),
statee varchar(30),
zip varchar(5),
county varchar(30) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES Employee (empid)
);
CREATE TABLE Service(
serviceid int NOT NULL,
serviceType varchar(30),
amount int,
PRIMARY KEY (serviceid)
);
CREATE TABLE Booking(
bookingid int NOT NULL AUTO_INCREMENT,
empid int NOT NULL,
custid int NOT NULL,
serviceid int NOT NULL,
PRIMARY KEY (bookingid),
FOREIGN KEY (empid) REFERENCES Employee (empid),
FOREIGN KEY (custid) REFERENCES Customer (custid),
FOREIGN KEY (serviceid) REFERENCES Service (serviceid)
);
CREATE TABLE Availability(
empid int NOT NULL,
datee date NOT NULL,
startTime int NOT NULL,
PRIMARY KEY (empid, datee, startTime),
FOREIGN KEY (empid) REFERENCES Employee (empid)
);
CREATE TABLE Transactions(
bookingid int NOT NULL,
paymentMethod varchar(20),
serviceid int,
amount int,
PRIMARY KEY (bookingid),
FOREIGN KEY (bookingid) REFERENCES Booking (bookingid),
FOREIGN KEY (serviceid) REFERENCES Service (serviceid)
);
I am trying to write a query that returns the bookingid, firstName, lastName, street, door no, zip code, serviceType, date and startTime GIVEN empid.
It is essentially a join of 5 tables and I'd implemented the query as:
SELECT B.bookingid, C.fname, C.lname, AD.street,
AD.doorno, AD.zip,S.serviceType, A.datee, A.startTime
FROM booking as B, availability as A, customer as C,
address as AD, Service as S
WHERE
B.empid=501 AND B.custid=C.custid
AND C.custid=AD.id
AND B.serviceid=S.serviceid AND B.empid=A.empid;
The REQUIRED results should have been:
BookingID fname lname street doorno zipcode serviceType date starttime
1 X Y ABC 33 5335 Clean 2015-05-20 9
2 P Q NMO 55 8294 Shift 2015-06-11 11
But the results give me the cross product of tables:
BookingID fname lname street doorno zipcode serviceType date starttime
1 X Y ABC 33 5335 Clean 2015-05-20 9
1 X Y ABC 33 5335 Shift 2015-06-11 11
2 P Q NMO 55 8294 Clean 2015-05-20 9
2 P Q NMO 55 8294 Shift 2015-06-11 11
Please let me know what is wrong with my query.
The primary key for Availability is currently (empid, datee, startTime), yet the JOIN is done on just on Booking.empid - it is possible there is more than one availability row per Employee.
I believe you will need to add a timestamp to Booking and interpolate on date during the join to Availability:
CREATE TABLE Booking(
-- ...
bookingDate datetime NOT NULL,
-- ...
);
I would also suggest that you add and end datetime bounds to the Availability, and store Date and Time as one (otherwise you will need to continually add the time back in):
CREATE TABLE Availability(
-- ...
startDateTime datetime NOT NULL,
endDateTime datetime NOT NULL,
PRIMARY KEY (empid, startDateTime), -- Put some rules to prevent overlap
);
The query then interpolates Booking to Availability on Date and Time:
SELECT B.bookingid, C.fname, C.lname, AD.street, AD.doorno, AD.zip,
S.serviceType, A.startDateTime
FROM
booking as B
INNER JOIN customer as C
ON B.custid=C.custid
INNER JOIN availability as A
ON B.empid=A.empid AND b.bookingDate BETWEEN A.startDateTime AND A.endDateTime
INNER JOIN address as AD
ON C.custid=AD.id
INNER JOIN Service as S
ON B.serviceid=S.serviceid
WHERE
B.empid=501;
I've also adjusted the join to use JOIN ON rather than doing the join in the WHERE.
This would address the duplicated availability data. However, I can't see how ServiceType would be different for the same booking.
You can use DISTINCT to eliminate duplicate records. Also always try to use explicit joins.
SELECT DISTINCT B.bookingid, C.fname, C.lname, AD.street,
AD.doorno, AD.zip,S.serviceType, A.datee, A.startTime
FROM booking as B
INNER JOIN availability as A ON B.empid = A.empid
INNER JOIN customer as C ON B.custid = C.custid
INNER JOIN address as AD ON C.custid = AD.id
INNER JOIN Service as S ON B.serviceid = S.serviceid
WHERE B.empid = 501

mysql data retrieval questions

rental table:
CREATE TABLE RENTAL
(
TransactionNo int NOT NULL AUTO_INCREMENT,
MemberID int NOT NULL,
ItemNo char(3) NOT NULL,
RentalEmployeeID varchar(30),
ReturnEmployeeID varchar(30),
Checkout_date DATE,
Checkin_date DATE,
Return_date DATE,
ItemQuantity int(11) NOT NULL,
TotalPrice DOUBLE(10,2) NOT NULL,
ItemFee DOUBLE(10,2),
PRIMARY KEY(TransactionNo),
FOREIGN KEY(MemberID) REFERENCES Member(MemberID),
FOREIGN KEY(ItemNo) REFERENCES Item(Itemno),
FOREIGN KEY(RENTALEMPLOYEEID) REFERENCES Employee(EmployeeID),
FOREIGN KEY(RETURNEMPLOYEEID) REFERENCES Employee(EmployeeID)
)
I am trying to retrieve the query for all of the customers that have purchased at least 2 items on the same day, however; i am still unable to accomplish it. Is a nested clause necessary for this?
my statement:
SELECT m.MemberID, r.`checkout_date`, SUM(r.itemquantity)
FROM RENTAL AS r, MEMBER AS m
WHERE r.MemberID = m.MemberID
GROUP BY m.MemberID, r.`checkout_date`
HAVING SUM (r.itemquantity) > 1
This new statement will give me what i want, however; because the rental information is not required(NULL) it sums up all of the return items as well and not the just rental.
You dont need a nested clause - 'GROUP BY' does the trick.
SELECT m.MemberID, r.`checkout_date`, COUNT(r.itemno)
FROM RENTAL AS r, MEMBER AS m
WHERE r.MemberID = m.MemberID
GROUP BY r.MemberID, `r.checkout_date`
group by memberid, checkoutdate having count(transactionid) > 1