PERSON - Email ID, Phone No, Address, Name, Age, Sex
ORDER - No of orders, Recipe, Ingredients, Email ID, Order ID, Order Status
ADDRESS - Address, Store Location, Mobile No
Suppose these are the three tables in a database and the respective columns.
what will be the query for getting the recipe which has the highest sale in each store?
i used this query but it shows half the result.
select distinct Store_Location, Recipe, No_of_Orders
from [ORDER]
join PERSON on [ORDER].Email_ID = PERSON.Email_ID
join ADDRESS on PERSON.Address = ADDRESS.Address
Like this:
select distinct Store_Location, Recipe, No_of_Orders
from [ORDER] As o
join PERSON As p on o.Email_ID = p.Email_ID
join ADDRESS As a on p.Address = a.Address
WHERE No_of_Orders = (
select MAX(o2.No_of_Orders)
from [ORDER] As o2
join PERSON As p2 on o2.Email_ID = p2.Email_ID
join ADDRESS As a2 on p2.Address = a2.Address
Where a2.Address = a.Address
)
This query works by comparing the rows of the original query to a subquery that returns the maximum No_of_Orders for the current row's store. If they match, then this must be the row of "the recipe which has the highest sale for this store", so we keep it, otherwise we exclude it from the final rowset.
The As o, As o2 bits are called "Table Aliases". They are a way to give a local name to each different usage of a table within a query. They are necessary here because in the subquery we are re-querying the same tables as in the outer query and we need to be able to distinguish which ones we mean for each column we reference.
Related
I am trying to select which co-ordinates from OA table are NOT found in the CUSTOMER address table.
SELECT DISTINCT
OA.CO_ORDS
FROM
CUSTOMER
INNER JOIN
OA ON customer.address=oa.co_ords
ORDER BY ID ASC;
Returns the co-ordinates which ARE in the customer table. How do I return those that are not in the customer table?
Am I also able to COUNT how many of customers are is in each co-ordinate (The co-ords are not specific and not accurate, this is purely for query testing only)
SELECT DISTINCT
OA.CO_ORDS
FROM
CUSTOMER
INNER JOIN
OA ON customer.address=oa.co_ords
ORDER BY ID ASC;
We can use NOT EXISTS to find those co-ordinates which don't appear in the customer table:
SELECT co_ords
FROM oa
WHERE
NOT EXISTS
(SELECT 1 FROM customers
WHERE address = oa.co_ords)
ORDER BY id;
In order to count how many customers belong to a certain co-ordinate, we can use COUNT with GROUP BY, something like this:
SELECT c.address, COUNT(*)
FROM customers c
JOIN oa
ON c.address = oa.co_ords
GROUP BY c.address;
It could be better to count a specific column instead of *.
It could also be better to use an IN clause instead of JOIN the tables:
SELECT c.address, COUNT(*)
FROM customers c
WHERE address IN
(SELECT co_ords FROM oa)
GROUP BY c.address;
Such details depend on your exact table structure, you should please try this out or provide more details.
You could also do:
SELECT co_ords
FROM oa
MINUS
SELECT address
FROM customers;
which can sometimes be faster than doing an anti-join. Note that MINUS does a distinct on the resultset.
I have a situation when it's needed to have a row of customer info (name, address, number etc.) and a count of cars he has. Each person are able to have any count of cars (car_name, VIN etc.)
And so i need to have a view with record info about customer and count of cars he has
SQL query
SELECT customer.id, customer.name, COUNT(car.id), customer.ipn, customer.address
FROM customer
LEFT JOIN car ON customer.id = car.customer_id
Everything OK for customers, that have cars, but for those, who not, bad, because they are not shown. I want to see zero, as well
DATA SET
TABLE 'Customer'
TABLE 'Car'
VIEW RESULT
Use Join with Group By
SELECT cu.id,cu.name,COUNT(cu.id) AS [COUNT],cu.ipn,cu.address,cu.number,cu.email
FROM Customer cu
JOIN Car ca ON cu.id = ca.customer_id
GROUP BY cu.id,cu.name,cu.ipn,cu.address,cu.number,cu.email
I will introduce my problem with a simple example.
I have two generic queries on the same table, say table 'customers'
Defined 'plushes' a table containing information about in-store plushes, the following first query retrieves for a certain subset of Customers, say first subset, their preferred plush.
WITH preferences
AS
(
SELECT CustomerID,
CustomerName,
City,
Country,
PlushType,
PlushPrice
FROM customers cs
LEFT JOIN plushes ps
ON cs.CustomerID = ps.CustomerID
WHERE cs.CustomerID < 4
)
SELECT CustomerID, PlushType, PlushPrice
FROM preferences
In the same way, defined 'dishes' a table containing world famous dishes, the second query retrieve for a another subset of Customers, say second subset, their preferred dish.
WITH foodPreferences
AS
(
SELECT CustomerID,
CustomerName,
City,
Country,
FoodName,
FoodPrice
FROM customers cs
LEFT JOIN foods fs
ON cs.CustomerID = fs.CustomerID
WHERE fs.FoodName = 'pizza'
)
SELECT CustomerID, FoodName
FROM foodPreferences -- it returns customer 6
What I am searching for, is a query that shows customerID, plushType, plushPrice for the customers of the first OR the second subset, i.e. :
That means, I would like to apply the first query to the first OR a second (deriving from another query) subset.
In other words, I want to run the first query for those customers who love pizza.
I am using OracleDB, with PL/Sql language.
Any idea?
P.s. I know that for the written example the structure of the used queries appears weird. Indeed, I am working with something more complex and I preferred to mirror the structure of the query I have
Added this new answer that is more efficient:
with selected_customers (customerid) as (
select customerid
from customers
where customerid < 4
union
select customerid
from customers
left join foods fs on cs.customerid = fs.customerid
where fs.foodname = 'pizza'
)
select customerid, ps.plushtype, ps.plushprice
from selected_customers cs
left join plushes ps on cs.customerid = ps.customerid;
This query will do:
select customerid, plushtype, plushprice
from customers cs
left join plushes ps on cs.customerid = ps.customerid
where customerid in (
select customerid
from customers
where customerid < 4
)
or customerid in (
select customerid
from customers cs
left join foods fs on cs.customerid = fs.customerid
where fs.foodname = 'pizza'
);
I have three tables:
Carrier(CarrierID(PK), FirstName, LastName)
Customer(CustomerID(PK), FirstName, LastName, RouteID(FK))
Route(RouteID(PK), CarrierID(FK), RouteName)
Each Route only has one carrier.
I need to display the count of customers that each carrier is responsible for.
I know I need to use the CarrierID to get the RouteID, and then use the RouteID to count the rows of Customers with that RouteID.
Can someone explain to me how that SELECT statement would look?
If you need the distinct number of customer you can use count(distinct ..) group by and join
select r.CarrierID, count(distinct CustomerID )
from Route r
inner join Customer c on c.RouteID = r.RouteID
group by r.CarrierID
select r.CarrierID, c2.Firstname, c2.Lastname, count(distinct CustomerID )
from Route r
inner join Customer c on c.RouteID = r.RouteID
inner join Carrier c2 on c2.CarrierID = r.CarrierID
group by r.CarrierID, c2.Firstname, c2.Lastname
Let's say i have 2 tables Customer and Books.
Table Books can have multiple rows that pertain to a row in Customer.
Ex:
customer John Doe has an id of 1000.
Table Books has 2 rows with a member_id column with 1000 (John Doe).
These 2 rows are identical EXCEPT one of the fields (book title) is empty. The other row has a value for a title.
Question:
How can i query this so that I retrieve the row with the valid title value, BUT, if both title values are empty, then it just returns a single row?
I certainly hope that made sense.
You should be able to use a distinct operator:
SELECT DISTINCT Customers.member_id, Books.book_title
FROM Customers
INNER JOIN Books ON Customers.member_id = Books.member_id
If that does not work correctly you could use an inner select:
SELECT DISTINCT *
FROM (SELECT Customers.member_id, Books.book_title
FROM Customers
INNER JOIN Books ON Customers.member_id = Books.member_id) As newTable
Also, if this is a frequently used query I would avoid a UNION because they are known to have performance problems.
In response to the edit:
SELECT Customers.member_id, Customer_Info.Name, ISNULL(newTable.book_title, '')
FROM Customers
INNER JOIN Customer_Info
LEFT JOIN (SELECT DISTINCT member_id, book_title FROM Books) newTable
ON newTable.member_ID = Customers.member_id
This should return all books associated with a customer (but only one time for each title and if no books are found then it will return an empty string.) If this does not answer the question please include some additional information about the tables and an example of the result you would like and I will update.
OK, now I think I know what you are looking for:
Here is a possible query based on your original question using the tables provided. However, it will not work if the customer has two distinct e-mail addresses set; in that case, you could add a TOP(1) to ensure only one result but you won't know if it is the "right result."
SELECT Customers.member_id, Office.Office_Name, ISNULL(newTable.email, '')
FROM Customers
INNER JOIN Office
LEFT JOIN (SELECT DISTINCT member_id, email
FROM Books
WHERE email IS NOT NULL AND email <> '') newTable
ON newTable.member_ID = Customers.member_id
Here is another query based on the data you provided and the example output.
SELECT Member_Name, Email
FROM thridTable
WHERE Member_Name = #SomeInputParameter
I'm not sure how representative your sample data is but why would you be storing the member name in more than one table? That is a guaranteed headache in the future.
If I understand what you're saying, this query will return all records with a non-null book title plus all customer records that have no valid book records, valid being defined as a book record with a non-null title.
SELECT c.id, c.name, b.title
FROM customer c
JOIN book b ON c.id = b.customer_id
WHERE b.title IS NOT NULL
UNION ALL
SELECT c.id, c.name, NULL
FROM customer c
WHERE NOT EXISTS (SELECT title FROM book b WHERE customer_id = c.id AND title IS NOT NULL)
You can use:
isnull(BOOKTITLE,'') = ''
on that field and a distinct, and it should give one result