SQL statement workflow - mysql

Every month we need to create a statement based off of a CSV file. Here is an example:
SELECT Name, OrderID, Product, Price
From Orders
Where OrderID = (here is where I am stuck);
So basically every month we get a new set of roughly 50 to 60 OrderID values in CSV format. How can I create a statement that outputs Name, OrderID, Product, Price for these OrderID's?

I think you are looking for something like this.
SELECT Name, OrderID, Product, Price
From Orders
Where OrderID In ('row1', 'row2', 'row3', ...);

Assuming you can put the IDs in a comma delimited list you would use an IN clause:
SELECT Name, OrderID, Product, Price
From Orders
Where OrderID IN (23,567,78);

Related

How to use a column in select statement which is not in aggregate function nor in group by clause? [duplicate]

This question already has answers here:
Retrieving the last record in each group - MySQL
(33 answers)
Closed 10 months ago.
Above is the table and on the basis of which I have to answer the below question in my past interview.
Q. The most recent order value for each customer?
Answer which I have given in interview:
select customerID, ordervalue, max(orderdate)
from office
group by customerID;
I know since we are not using ordervalue in aggregate and nor in group by so this query will throw an error in SQL but I want to know how to answer this question.
Many times in my past interviewers asked a question where I need to use a column in select statement which is not in aggregate function or nor in group by. So I want know in general what is a workaround for it with an example so that I can resolve these type of questions or how to answer these questions.
The work around depends on what is being asked. For the requirements you have above, I think it makes sense to create (customerid, MAX(orderdate)) pairs.
SELECT customerid, MAX(orderdate)
FROM office
GROUP BY customerid;
Then you can use them to match the row you need from the table.
SELECT customerid, ordervalue, orderdate
FROM office
WHERE (customerid, orderdate) IN
(SELECT customerid, MAX(orderdate)
FROM office
GROUP BY customerid);
Note, this assumes there is only one order per customer per day. If there were more than one, you would see the most recent order(s) per customer. You could add also a GROUP BY on the outer query if needed.
SELECT customerid, MAX(ordervalue), orderdate
FROM office AS tt
WHERE (customerid, orderdate) IN
(SELECT customerid, MAX(orderdate)
FROM office
GROUP BY customerid)
GROUP BY customerid, orderdate;
If the non-aggregate column you need in the SELECT is functionally dependent on the column in the GROUP BY, you can add a subquery in the SELECT.
We can extend your example by adding a name column, where the name of different customers could be the same. If you wanted name instead of ordervalue, just match the customerid of the outer query to get name.
SELECT customerid,
(SELECT name FROM office WHERE customerid=o.customerid LIMIT 1) AS name,
MAX(orderdate)
FROM office AS o
GROUP BY customerid;
You are approaching the task as follows: Aggregate all rows to get one result line per customer, showing the maximum order date and its order value. The problem with this: you'd need an aggregate function to get the value for the maximum order date. The only DBMS I know of featuring such a function is Oracle with KEEP FIRST/LAST.
So look at the task from a different angle. Don't think aggregation-wise where you could count and add up values for a group and get the minimum or maximum value over all the group's rows, because after all you just want to pick single rows. (That is, pick the top 1 row per customer.) In order to pick rows, you'll use a WHERE clause.
One option has been shown by Steve in his answer:
select *
from office
where (customerid, orderdate) in
(
select customerid, max(orderdate)
from office
group by customerid
);
This is a good, straight-forward approach. (Some DBMS, though, don't feature tuples with IN clauses.)
Another way to get the "best" row for a customer would be to pick those rows for which not exists a better row:
select *
from office
where not exists
(
select null
from office better
where better.customerid = office.customerid
and better.orderdate > office.orderdate
);
And then there is the option to use a window function (aka analytic function) in order to get those rows. One example is to get the maximum dates along with the rows' data:
select customerid, ordervalue, orderdate
from
(
select
customerid, ordervalue, orderdate,
max(orderdate) over (partition by customerid) as max_orderdate
from office
)
where orderdate = max_orderdate;
And with ROW_NUMBER, RANK, and DENSE_RANK there are window functions to assign numbers to your rows in the order you want. You number them such that the best rows get number 1 and pick them. The big advantage here: you can apply any order, deal with ties and not only get the top 1, but the top n rows.
select customerid, ordervalue, orderdate
from
(
select
customerid, ordervalue, orderdate,
row_number() over (partition by customerid order by orderdate desc) as rn
from office
)
where rn = 1;

How to get pin codes without zeros in it?

Write a query to display the customer_id,customer full name ,city,pincode,and order details (order id, product class desc, product desc, subtotal(product_quantity * product_price)) for orders shipped to cities whose pin codes do not have any 0s in them. Sort the output on customer name and subtotal. (52 ROWS) [NOTE: TABLE TO BE USED - online_customer, address, order_header, order_items, product, product_class].
These are the attributes of each table:
Address- ADDRESS_ID, ADDRESS_LINE1,ADDRESS_LINE2,CITY,STATE,PINCODE,COUNTRY
ONLINE_CUSTOMER- CUSTOMER_ID, CUSTOMER_FNAME, CUSTMER_LNAME, CUSTOMER_EMAIL,CUSTOMER_PHONE, ADDRESS_ID, CUSTOMER_CREATION_DATE,CUSTOMER_USERNAME, CUSTOMER_GENDER
ORDER_HEADER- ORDER_ID, CUSTOMER_ID, ORDER_DATE, ORDER_STATUS, PAYMENT_MODE, PAYMENT_DATE, ORDER_SHIPMENT_DATE,SHIPPER_ID
ORDER_ITEMS- ORDER_ID, PRODUCT_ID, PRODUCT_QUANTITY
PRODUCT- PRODUCT_ID, PRODUCT_DESC, PRODUCT_CLASS_CODE, PRODUCT_PRICE, PRODUCT_QUANTITY_AVAIL, LEN, WIDTH, HEIGHT, WEIGHT
PRODUCT_CLASS- PRODUCT_CLASS_CODE, PRODUCT_CLASS_DESC
Can anyone help me on how to filter pincodes without any zeros in it and order status as shipped.
Test if no zeros exist
where length(replace(pincode,'0','')) = length(pincode)
or
where instr(pincode,'0') = 0
or you could use regex or test valid pincodes by downloading and validating

MySQL - Average number of particular product sold on date

I need to write SQL query for "average number of particular product sold by date. On each day is sold min one product".
SELECT AVG (COUNT (PID))
FROM SOLD
GROUP BY DATE, PID;
P.S. PID means Product ID.
Is this query okay?
Should this give right answer?
Consider Using distinct count of date columns
SELECT PID,
COUNT(PID)/COUNT(distinct date_) as "Avg.Product Sold By Days"
FROM SOLD
GROUP BY PID;
You can try this sql query below. Basically, it will return the average number of 'SALES' for each product you have. It will group by each distinct product ID. Please provide us the data structure your of table and etc.
SELECT product_ID, trans_date
Sum(sales_of_product) / COUNT(DISTINCT sold_transaction) AS 'avg'
FROM SOLD
GROUP BY product_ID

Query to tell me if customer is in 3 queries

I have three queries;
Q1. Returns all customer records (id, name, year amount) where the customer has spent money with us.
Q2. Returns all customers records (id,name, year of regis, number) where the customer has a telephone number.
Q3. Returns all customer records (id,name, year, amount) where the customer has a purchased a specific product.
I want a new query that will return a list of all customers ids, names if they appear in any of the 3 queries, along with the latest year. How do I do that?
First, add all the results of the 3 queries together using UNION, then group the records by id and select the first name (or any name really, because they must be all the same) and the maximum year.
Try this:
SELECT id, FIRST(name), MAX(year)
FROM (
SELECT id, name, year FROM q1
UNION
SELECT id, name, year FROM q2
UNION
SELECT id, name, year FROM q3) AS q
GROUP BY id

SELECT the customer who has ordered the greatest quantity of Products in the case of two customers

I have the following ORDERS table
I know query to select the customer that has ordered the greatest quantity. However, how would it work, if say, two customers have the same quantity. What query should I write to show both the customers?
You can use a subquery which checks that the quantity for a given record matches the largest quantity observed in the table:
SELECT *
FROM yourTable
WHERE qty = (SELECT MAX(qty) FROM yourTable)
This will return multiple records if there are more than one customer sharing the maximum quantity.
If you only wanted to get back a single record, even in the presence of ties, you could use this approach:
SELECT *
FROM yourTable
ORDER BY qty DESC
LIMIT 1
I think you want sum of qty per custNum.
If so you can try like:
select custNum,
sum(qty) as qty
from Orders
group by custNum
order by sum(qty) desc;
Fiddle here:
http://sqlfiddle.com/#!9/47931b/10
SELECT custnum,sum(qty) as total
FROM orders
group by custnum
having sum(qty) = (SELECT MAX(qty) FROM orders);
This will return both values.