forming a subquery inside mysql? - mysql

List the customer number, customer name, and sales rep that have the same rep number as customer number 282. This will need to be a subquery and do not test for sales rep 35 explicitly. Let MySQL do the work for you. Insert your query and results here.
use premier_products;
select customer.customer_num,customer.customer_name,rep.first_name
(SELECT rep_num
from rep,customer
where rep.rep_num = customer.rep_num
and customer_num = 282)
from customer,rep;
im confused with how to form a subquery with the following question. the only two fileds that are related between the two tables is rep.rep_num = customer.rep_num.
AND REP.FIRST_NAME REFERS TO SALES REP...

You need to study about tables Join in MySql.
Your query doesn't need a subquery:
SELECT customer.customer_num, customer.customer_name, rep.first_name, rep.rep_num
FROM rep
JOIN customer
ON rep.rep_num = customer.rep_num
WHERE customer_num = 282;

Related

SELECT DISTINCT ON Simple Table Unique Values

I have two tables, one with unique LTV (lifetime values) with around 3300 records and then the transaction log with more than 5000 transactions.
Whenever I run the following query it keeps showing me duplicate values. I just want to look up the person's first name and last name from the first column.
SELECT
SociAll.firstname,
SociAll.lastname,
SociLTV.Email,
SociLTV.LTV
FROM
SociAll
INNER JOIN SociLTV ON SociAll.Email = SociLTV.Email
Sometimes the same email address is repeated 3 or 4 times depending on the number of transactions from that given user, even though the LTV is the exact same value.
How can I have only 1 record per email address on this Query?
Try this:
SELECT
SociAll.firstname,
SociAll.lastname,
SociLTV.Email,
Sum(SociLTV.LTV)
FROM
SociAll
INNER JOIN SociLTV ON SociAll.Email = SociLTV.Email
GROUP BY SociAll.firstName,SociAll.LastName,SociAll.Email
You can also use COUNT() or MIN(), or MAX() etc. on the last column. If you don't care at all about the last column, remove it.
You can also do the following if you don't care at all about the SocilTV records
SELECT DISTINCT
SociAll.firstname,
SociAll.lastname,
SociLTV.Email,
FROM
SociAll
INNER JOIN SociLTV ON SociAll.Email = SociLTV.Email
We don't need a sum of the LTV since the LTV already has the final value. To answer the question I had a list of lifetime values of each customer.
SELECT
SociAll.firstname,
SociAll.lastname,
SociLTV.Email,
SociLTV.LTV
FROM
SociAll
INNER JOIN SociLTV ON SociAll.Email = SociLTV.Email
GROUP BY SociAll.firstName,SociAll.LastName,SociAll.Email
If I wasn't comparing the two tables and simply had a list of transactions, this query works great. It's a derivative of your solution.
SELECT
SociAll.Email,
SociAll.firstname,
SociAll.lastname,
Sum(SociAll.Price) as LTV
FROM
SociAll
GROUP BY SociAll.firstName,SociAll.LastName,SociAll.Email
As I posed the question I was using a pre-established 'LTV' table export from a list of customers and their lifetime value from an excel spreadsheet.
Thank you so much for your contributions. I hope others find this post useful.

Group records by UserID, select where on one column value and sum another

Using SQL in MySQLWorkbench I'd like to group records by 'UserID',
select only the records that match where 'Weeks' are in(5,6,7,8) and sum the values for each user in 'Score'.
The records are actually stored in two tables that I am joining, a lineup table and lineup history table:
INNER JOIN vi_lineup on vi_lineup.lineup_master_id = vi_lineup_master.lineup_master_id
Obviously, I am a newbie. I did search S.O. first but did not find a matching question. I'll keep looking and hope someone answers here. Thanks for any help.
A comment asked about the Weeks. The game is based on a weekly model and we number them sequentially. Here's a working query joining the tables and selecting records based on the weeks:
select * FROM vi_lineup LU
INNER JOIN vi_lineup_master LM
WHERE (LU.week > 4 and LU.week < 9)
AND LU.lineup_master_id = LM.lineup_master_id
Limit 0,148000;
What I would like to do now is Group the records by LM.UserID and sum the values in LU.Score
Thanks!
You have not told us where userid or score comes from. But assuming you can clarify that yourself, the "basic" structure of the query will be like this:
SELECT
??.UserID, SUM(??.score) AS sum_score
FROM vi_lineup lu
INNER JOIN vi_lineup_master lm ON lu.lineup_master_id = lm.lineup_master_id
WHERE lu.week between 5 and 8
GROUP BY
??.UserID
You will need to replace each ?? with the correct table alias "lu" or "lm"

use data from multiple tables in SQL

need some quick help.. i think i'm supposed to use INNER JOIN, but i'm not really sure.
List the employee ID and the full name of the employee who sold or packaged the
transactions placed by customer Benjamin Jones. Each employee should only show up
once in your results
employeeID, first and last are in the EMPLOYEES table
benjamin jones' memberID is 101 and in the MEMBERS table
memberID and transactionID and soldorpackagedby are in the TRANSACTIONS table
this is what I have to start it off but don't know how to finish it.
SELECT EmployeeID, First, Last
FROM Employees
WHERE MemberID = '101'
thanks!
Try -
SELECT employees.EmployeeID,
employees.First,
employees.Last
FROM employees
JOIN transactions ON employees.EmployeeID = transactions.SoldOrPackagedBy
WHERE transactions.memberID = 101
GROUP BY employees.EmployeeID;
Because you are using data from more than one table in this SQL statement you will need to specify which table a repeated field name such as EmployeeID will come from, hence employees.EmployeeID. employee. is probably not called for in front of First and Last but I tend to put it in anyway since the habit can help avoid bugs occurring when I am writing more complex statements.
JOIN without INNER, LEFT, RIGHT or FULL in front is the same as INNER JOIN (see https://www.w3schools.com/sql/sql_join.asp).
Since the Member's ID is already known and used in the Transactions table, and we are not being asked to refer to any other detail about the member here, then there is no need to link in the Members table.
Without GROUP BY the SELECT statement will return a record for every time an Employee packaged a Transaction for a Member. These details would be the same every time. Using GROUP BY would reduce this to just one instance of those details.
If you have any questions or comments, then please feel free to post a Comment accordingly.
Try this one
SELECT employees.EmployeeID,
employees.First,
employees.Last
FROM employees
JOIN transactions ON employees.EmployeeID = transactions.EmployeeID
WHERE transactions.memberID = 101
GROUP BY employees.EmployeeID, employees.First, employees.Last ;

mysql multiple joins query not returning desired ouput

I have three tables customers, orders, payments
I am trying to get the record with inner join of a customer with his different orders and payment methods he use against the orders.
For example
customer_name Order_status Payment_method
David shipped CASH
David cancelled CHEQUE
When I run the query it repeats the record three times and result also not as I mention above in example.
Here is query.
SELECT cust_name
, order_status
, pay_method
FROM customer
INNER JOIN order_tbl ON customer.cust_id = order_tbl.cust_id
INNER JOIN payments ON payments.cust_id = order_tbl.cust_id
Is my query alright or do I need to mention my db structure as well?
You are missing a relationship there. Your orders and payments need to link together somehow, i'm assuming there should be an order_id column in both tables ?
SELECT cust_name
, order_status
, pay_method
FROM customer
INNER JOIN order_tbl
ON customer.cust_id = order_tbl.cust_id
INNER JOIN payments
ON payments.cust_id = order_tbl.cust_id
AND payments.order_id = orders_tbl.order_id --<<--- this line here is missing
If you dont have that kind of link, how do you logically link a payment to an order - because that will be your link that you're missing.
You are getting duplicate records because the criteria is matched, nothing wrong with MySQL, it's returning results based on what you asked. Have you checked the ID's of the duplicate records to make sure that they are different? It may be the same record with different payment ID, so it will definitely return the customer and order records that are related for each record that a relationship exists. You could use DISTINCT(THE_FIELD) if you want to make the query distinct based on some criteria.
I am answering with limited knowledge on your project based on the information you provided. As mentioned in the comment above, more information would get an even better answer.
You must probably missed using the primary key of order_tbl to join the third table.

How to store SQL Query result in table column

I'm aware of the INSERT INTO table_name QUERY; however, I'm unsure how to go about achieving the desired result in this case.
Here's a slightly contrived example to explain what I'm looking for, but I'm afraid I cannot put it more succiently.
I have two tables in a database designed for a hotel.
BOOKING and CUSTOMER_BOOKING
Where BOOKING contains PK_room_number, room_type, etc. and CUSTOMER_BOOKING contains FK_room_number, FK_cusomer_id
CUSTOMER_BOOKING is a linking table (many customers can make many bookings, and many bookings can consist of many customers).
Ultimately, in the application back-end I want to be able to list all rooms that have less than 3 customers associated with them. I could execute this a separate query and save the result in the server-side scripting.
However, a more elegant solution (from my point of view) is to store this within the BOOKING table itself. That is to add a column no_of_bookings that counts the number of times the current PK_room_number appears as the foreign key FK_room_number within the CUSTOMER_BOOKING table. And why do this instead? Because it would be impossible for me to write a single complicated query which will both include the information from all ROOMS, among other tables, and also count the occurrences of bookings, without excluding ROOMS that don't have any bookings. A very bad thing for a hotel website attempting to show free rooms!
So it would look like this
BOOKING: PK_room_number (104B) room_type (double) room_price (high), no_of_bookings (3)
BOOKING: PK_room_number (108C) room_type (single) room_price (low), no_of_bookings (1)
CUSTOMER_BOOKING: FK_room_number (104B) FK_customer_id (4312)
CUSTOMER_BOOKING: FK_room_number (104B) FK_customer_id (6372)
CUSTOMER_BOOKING: FK_room_number (104B) FK_customer_id (1112)
CUSTOMER_BOOKING: FK_room_number (108C) FK_customer_id (9181)
How would I go about creating this?
Because it would be impossible for me to write a single complicated
query which will both include the information from all ROOMS, among
other tables, and also count the occurrences of bookings, without
excluding ROOMS that don't have any bookings.
I wouldn't say it's impossible and unless you're running into performance issues, it's easier to implement than adding a new summary column:
select b.*, count(cb.room_number)
from bookings b
left join customer_booking cb on b.room_number = cb.room_number
group by b.room_number
Depending on your query may need to use a derived table containing the booking counts for each room instead instead
select b.*, coalesce(t1.number_of_bookings,0) number_of_bookings
from bookings b
left join (
select room_number, count(*) number_of_bookings
from customer_booking
group by room_number
) t1 on t1.room_number = b.room_number
You have to left join the derived table and select coalesce(t1.number_of_bookings,0) in case a room does not have any entries in the derived table (i.e. 0 bookings).
A summary column is a good idea when you're running into performance issues with counting the # of bookings each time. In that case I recommend creating insert and delete triggers on the customer_booking table that either increment or decrement the number_of_bookings column.
You could do it in a single straight select like this:
select DISTINCT
b1.room_pk,
c1.no_of_bookings
from cust_bookings b1,
(select room_pk, count(1) as no_of_bookings
from cust_bookings
group by room_pk) c1
where b1.room_pk = c1.room_pk
having c1.no_of_bookings < 3
Sorry i used my own table names to test it but you should figure it out easily enough. Also, the "having" line is only there to limit the rows returned to rooms with less than 3 bookings. If you remove that line you will get everything and could use the same sql to update a column on the bookings table if you still want to go that route.
Consider below solutions.
A simple aggregate query to count the customers per each booking:
SELECT b.PK_room_number, Count(c.FK_customer_id)
FROM Booking b
INNER JOIN Customer_Booking c ON b.PK_room_number = c.FK_room_number
GROUP BY b.PK_room_number
HAVING Count(c.FK_customer_id) < 3; # ADD 3 ROOM MAX FILTER
And if you intend to use a new column no_of_booking, here is an update query (using aggregate subquery) to run right after inserting new value from web frontend:
UPDATE Booking b
INNER JOIN
(SELECT b.PK_room_number, Count(c.FK_customer_id) As customercount
FROM Booking b
INNER JOIN Customer_Booking c ON b.PK_room_number = c.FK_room_number
GROUP BY b.PK_room_number) As r
ON b.PK_room_number = r.PK_room_number
SET b.no_of_booking = r.customercount;
the following generates a list showing all of the bookings and a flag of 0 or 1 if the the room has a customer for each of the rooms. it will display some rooms multiple times if there are multiple customers.
select BOOKING.*,
case CUSTOMER_BOOKING.FK_ROOM_NUMBER is null THEN 0 ELSE 1 END AS BOOKING_FLAG
from BOOKING LEFT OUTER JOIN CUSTOMER_BOOKING
ON BOOKING.PK_room_numer = CUSTOMER_BOOKING.FK_room_number
summing and grouping we arrive at:
select BOOKING.*,
SUM(case when CUSTOMER_BOOKING.FK_ROOM_NUMBER is null THEN 0 ELSE 1 END) AS BOOKING_COUNT
from BOOKING LEFT OUTER JOIN CUSTOMER_BOOKING
ON BOOKING.PK_room_number = CUSTOMER_BOOKING.FK_room_number
GROUP BY BOOKING.PK_room_number
there are at least two other solutions I can think of off the top of my head...