I'be been googling around about nested queries but can't find anything that I can grasp about how to go about this particular operation.
First, I'll show you my DB schema
CREATE TABLE slsemp
( empID char(4) NOT NULL,
empname varchar(50) NOT NULL,
prtime enum('yes','no') NOT NULL, # we can only accept yes or no values to the part-time employee indicator
RegionID char(2) NOT NULL, # enums are often used for boolean values in a BD
PosID char(4) NOT NULL,
PRIMARY KEY (empID),
FOREIGN KEY (regionID) REFERENCES region (RegionID),
FOREIGN KEY (PosID) REFERENCES slspos(PosID));
# create the sales transactions table
CREATE TABLE slstranx
( tranxID int(10) NOT NULL AUTO_INCREMENT, #starts at a certain number, then increments accordingly
empID char(4) NOT NULL,
ProdID char(3) NOT NULL,
Qty int(5) NOT NULL,
Unitprice Decimal(5,2) NOT NULL, # please note we are capturing the unit price at the transactional level in this case
SAmt Float(10,2), #store up to 10 (TOTAL?) with 2 digits past decimal point
SalesDate date, # 'date' data type is organized as follows YYYYMMDD. You need to make sure that raw data contains the DATE in the YYYYMMDD format
# For example 20150915
PRIMARY KEY (tranxID),
FOREIGN KEY (ProdID) REFERENCES product (ProdID),
FOREIGN KEY (empID) REFERENCES slsemp (empID));
Now, I want to find employees that are in the west region that haven't made any sales. I figured I'd do this via a left outer join between the two tables then query the resulting table based off of a null tranx ID. I've got it most of the way there, here's my query:
SELECT e.empID, t.tranxID, e.RegionID
FROM slsemp e LEFT OUTER JOIN slstranx t ON e.empID=t.empID
WHERE e.RegionID='WS'
My question is, how do I query based of the criteria of this resultant table. If I could do that, I simply would need a selection with criteria of slstranxID=null.
You can use left join adding where slstranx.empID is null
select distinct empID, empName
from slsemp
left join slstranx on slsemp.empID = slstranx.empID
where slsemp.RegionID = 'WS'
and slstranx.empID is null
if the column from the table in left join is null mean that don't match .. so don't have sales
Related
I have two tables one is a customer table and the second is sales table.
I need to create a query to display customer name, customer_id and number of Gadgets bought (write two queries using different syntaxes of JOIN). Example : “John Barry - 111 bought 5 gadgets”.
CUSTOMERS_JS
create table CUSTOMERS_JS (
CUSTID smallint not null,
CUSTNAME char(50) not null,
primary key(CUSTID)
);
STORE_SALES_JS
create table STORE_SALES_JS (
SALEID smallint not null,
SALETS datetime not null,
GADGETID smallint not null,
EMPID smallint not null,
CUSTID smallint not null,
primary key(SALEID),
foreign key(GADGETID) references ELEC_items_JS(GADGETID),
foreign key(EMPID) references Store_EMPS_JS(EMPID),
foreign key(CUSTID) references CUSTOMERS_JS(CUSTID)
);
I did this query
select concat(CUSTNAME,' - ',STORE_SALES_JS.CUSTID,' bought ',count(STORE_SALES_JS.GADGETID),' gadgets') as result
from CUSTOMERS_JS,STORE_SALES_JS
where STORE_SALES_JS.CUSTID = CUSTOMERS_JS.CUSTID
group by STORE_SALES_JS.CUSTID,CUSTNAME
order by STORE_SALES_JS.CUSTID
but there is too much space between the name and the '-'. I tried to change the name field to varchar and it worked as it supposed to work but I need it to work with char(50) as well.
Thanks to scaisEdge help I managed to fix this issue while using rtrim function
select concat(rtrim(CUSTNAME),' - ',STORE_SALES_JS.CUSTID,' bought ',count(STORE_SALES_JS.GADGETID),' gadgets') as result
from CUSTOMERS_JS,STORE_SALES_JS
where STORE_SALES_JS.CUSTID = CUSTOMERS_JS.CUSTID
group by STORE_SALES_JS.CUSTID,CUSTNAME
order by STORE_SALES_JS.CUSTID
if you must use char and not varchar but need a trimmed result in your select you could trim ( or rtrim or ltrim) your custname for remove the spaces
select concat(rtrim(CUSTNAME),' - '
,STORE_SALES_JS.CUSTID,' bought '
,count(STORE_SALES_JS.GADGETID),' gadgets') as result
from CUSTOMERS_JS,STORE_SALES_JS
where STORE_SALES_JS.CUSTID = CUSTOMERS_JS.CUSTID
group by STORE_SALES_JS.CUSTID,CUSTNAME
order by STORE_SALES_JS.CUSTID
lets say I have an account object in my application, which currently represented as:
CREATE TABLE Account (
accountId int NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
PRIMARY KEY (accountId)
);
Now, Account object need to also have Solution field...and Status have 4 different possible values:
Solution1, Solution2, Solution3, Solution4
What would be the right way to represent it in the database?
Account can have few statuses, and status can have few accounts...
So at first I thought create in the db table of Solutions and than have another table to hold the relationship, but its seems too complicated for a field that have only 4 possible values...
Create a junction table to represent the relationships between accounts and solutions:
CREATE TABLE account_solution (
accountId int NOT NULL,
solutionId int NOT NULL
PRIMARY KEY (accountId, solutionId)
)
For your solution table, since there are only 4 values, you might be able to take advantage of MySQL's enum type, e.g.
CREATE TABLE solution
solutionId int NOT NULL PRIMARY KEY,
status ENUM('Solution1', 'Solution2', 'Solution3', 'Solution4')
);
You can use set Mysql SET type
CREATE TABLE Account (
accountId int NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
status set('Solution1','Solution2','Solution3','Solution4') NOT NULL,
PRIMARY KEY (accountId)
);
And if you want to select a specific status
SELECT *
FROM `Account`
WHERE FIND_IN_SET( 'Solution2', `status` ) >0
I have the following inside my stored procedure that retrieves unique records from player names that have a faction of Neutral:
SELECT
COUNT(DISTINCT Name) into #neutcount
FROM
dim5players
WHERE
Faction ='Neutral';
UPDATE dim5stats
SET Value = #neutcount
WHERE
Function = 'Neutral';
This works find and dandy. The problem is that I have a field called Date as well.
I want to select the lastest date of the records to be listed in the count instead of a random record from the unique "Name" record.
This is a history table, and it records daily changes of the records, where Name can appear several times. I need to count only the latest records that have a faction of neutral with their latest records only. Some people change factions from time to time. I only care about their latest faction.
This is the structure:
CREATE TABLE `dim5players` (
`id` CHAR(64) NOT NULL,
`name` VARCHAR(45) NOT NULL,
`rank_name` VARCHAR(20) NULL DEFAULT NULL,
`level` INT(11) NOT NULL,
`defender_rank_id` INT(11) NULL DEFAULT NULL,
`Faction` VARCHAR(15) NOT NULL,
`Organization` VARCHAR(100) NULL DEFAULT NULL,
`Date` DATE NOT NULL,
`Updated` BIT(1) NOT NULL,
UNIQUE INDEX `id_UNIQUE` (`id`) USING HASH,
INDEX `name_index` (`name`) USING HASH,
INDEX `date_index` (`Date`) USING HASH,
INDEX `updated_index` (`Updated`) USING HASH,
INDEX `faction_index` (`Faction`) USING HASH
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
After a discussion with Michael i think i figured out what he needs:
"I want the Last Updated record of each name"
SELECT
name ,
MAX(Date) as last_date
FROM
dim5players
WHERE
Faction ='Neutral'
GROUP BY
name
"I just want to count the latest date on each NAME that still holds the faction of Neutral"
SELECT
COUNT(last_date)
FROM (
SELECT
name ,
MAX(Date) as last_date
FROM
dim5players
WHERE
Faction ='Neutral'
GROUP BY
name
) as tmp
#Michael : Let me know if i understood you requirements correctly
I have the following 3 tables as part of a car booking system:
CREATE TABLE `b_booking` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`b_car_id` VARCHAR(15) NOT NULL,
`uc_user_id` INT(11) NOT NULL,
`booking_date` DATE NOT NULL,
`delivery_date` DATE NOT NULL,
`delivery_location` INT(10) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `FK_b_booking_b_car` (`b_car_id`),
INDEX `FK_b_booking_uc_users` (`uc_user_id`),
INDEX `FK_b_booking_b_location` (`delivery_location`),
CONSTRAINT `FK_b_booking_b_location` FOREIGN KEY (`delivery_location`) REFERENCES `b_location` (`id`),
CONSTRAINT `FK_b_booking_b_car` FOREIGN KEY (`b_car_id`) REFERENCES `b_car` (`id`),
CONSTRAINT `FK_b_booking_uc_users` FOREIGN KEY (`uc_user_id`) REFERENCES `uc_users` (`id`)
CREATE TABLE `b_car` (
`id` VARCHAR(15) NOT NULL,
`b_carmodel_id` INT(10) NOT NULL,
`day_cost` INT(10) NOT NULL,
`location` INT(10) NOT NULL,
`model_year` SMALLINT(4) NOT NULL,
PRIMARY KEY (`id`),
INDEX `FK_b_car_b_carmodel` (`b_carmodel_id`),
INDEX `FK_b_car_b_location` (`location`),
CONSTRAINT `FK_b_car_b_location` FOREIGN KEY (`location`) REFERENCES `b_location` (`id`),
CONSTRAINT `FK_b_car_b_carmodel` FOREIGN KEY (`b_carmodel_id`) REFERENCES `b_carmodel` (`id`)
CREATE TABLE `b_location` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`adress` VARCHAR(100) NOT NULL,
`b_postal_zip` SMALLINT(4) UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
INDEX `FK_b_location_b_postal` (`b_postal_zip`),
CONSTRAINT `FK_b_location_b_postal` FOREIGN KEY (`b_postal_zip`) REFERENCES `b_postal` (`zip`)
A given car (b_car) will have an int representing av location where a car can be picked up or delivered. However, this location will change, due to the fact that a customer can pick up the car on one location, and deliver at another. When a customer registers a booking (b_booking), he/she also register at what location the car will be delivered (delivery_location).
I'm however having a lot of problems with what seems to me shouldn't be that hard to do: Lets say a car is at location 1 at the beginning of the month. Then, customer X register a booking for 15-20. and registers a delivery at location 2. Then customer Y wishes to book the same car. So I need a query which takes into account the date and location.
SELECT c.id, c.location, b.delivery_location, MAX(b.delivery_date) FROM b_car c
LEFT JOIN b_booking b ON b.b_car_id = c.id
WHERE b.delivery_date < '2012-11-28' OR b.delivery_date IS NULL
GROUP BY c.id;
I have tried something similar to this. I will pick all cars which has no bookings with the left join, and it will also pick the last booking (the last booking related to given date). The problem is, of course, that the where condition also excludes any booking with a date higher than the provided date. Also, with this solution I'm forced to get both the location (from b_car) and the delivery location (from b_booking), and perhaps evaluate null on the delivery_location with php or something.. which really doesnt seem optimal.
Any good solutions?
Thanks
I am not sure what your question is. I think your question is to find out which cars are available based on the planning in the booking system on a given day. In that case the only info you need is the ids from the cars and the location and according to the booking system.
BTW I would suggest to add time to your table, because you may want to rent out a car the same day. If customer A returns the car before 12:00 you can easily rent out the same car at 13:00 to customer B.
SELECT c.id, b.delivery_location, b.delivery_date FROM b_car AS c
LEFT JOIN b_booking AS b ON b.id = c.id
WHERE b.delivery_date = '2012-11-28' and b.delivery_location = 1;
I simplified you query, because I think this will give you the information you need. If a customer wants to rent a car you need to know if the car is available in the planning at the specified location.
If you want to know the availability between to dates use WHERE b.delivery_date between [start date] AND [end date].
I suspect that the type of car is important for the customer, so perhaps it is better to look for a specific car type available at the location of choice.
Furthermore, I would suggest checking if the car is actual at the desired location at the delivery time.
I have 2 tables city_sessions_1 and city_sessions_2
Structure of both table are similar
CREATE TABLE `city_sessions_1` (
`city_id` int(11),
`session_date` date,
`start_time` varchar(12),
`end_time` varchar(12) ,
`attendance` int(11) ,
KEY `city` (`city_id`),
KEY `session_date` (`session_date`)
) ENGINE=MyISAM;
Note these tables do not have any primary key, but they have their indexes defined. Both tables have same number of rows. But it is expected that some data would be different.
How can I compare these 2 tables' data?
-- We start with the rows in city_session_1, and their fit in city_session_2
SELECT
* -- or whatever fields you are interested in
FROM city_sessions_1
LEFT JOIN city_sessions_2 ON city_sessions_1.city_id=city_sessions_2.city_id
WHERE
-- Chose only those differences you are intersted in
city_sessions_1.session_date<>city_session_2.session_date
OR city_sessions_1.start_time<>city_session_2.start_time
OR city_sessions_1.end_time<>city_session_2.end_time
OR city_sessions_1.attendance<>city_session_2.attendance
UNION
-- We need those rows in city_session_2, that have no fit in city_session_1
SELECT
* -- or whatever fields you are interested in
FROM city_sessions_2
LEFT JOIN city_sessions_1 ON city_sessions_1.city_id=city_sessions_2.city_id
WHERE city_sessions_1.city_id IS NULL