I have 2 tables, restaurants and orders, each restaurant has many orders
restaurants table
id
name
orders table
id
restaurant_id
date
status
if for some date there is no order - it means there is no row in orders table. If there is an order, its status can be 0, 1 or 2. Each row in orders table represents one day.
I need to find those restaurants that, say between 2013-08-15 and 2013-08-25(that includes current day - 2013-08-19 ) do not have orders at all (which means there is no appropriate row in orders table), or have order status 0 or 1, but along with these conditions the order for today should have status - 2. So, if some restaurant do not have order for today or its status is not 2 - this restaurant should not be listed in the result, but if the order for today exists and its status is 2 the result should contain that restaurant with all the orders list for the above-mentioned date range.
By this query I get the result without the part of today's condition.
SELECT r.`id`, r.`name`
FROM restaurants r
LEFT JOIN orders o ON r.id = o.restaurant_id AND o.date between '2013-08-15' AND '2013-08-25'
where o.id is null OR o.`status` = 0 OR o.status = 1
How can I add that condition as well ?
Thanks
I would do the queries separately and take the union of the results.
Exclude today from the query you have, add a separate query for today.
Something like:
SELECT r.id, r.name
FROM restaurants r
LEFT JOIN orders o
ON r.id = o.restaurant_id
AND o.date between '2013-08-15' AND '2013-08-25'
AND o.date <> '2013-08-19' -- current day
where o.id is null OR o.status = 0 OR o.status = 1
UNION
SELECT r.id, r.name
FROM restaurants r
INNER JOIN orders o
ON r.id = o.restaurant_id
AND o.date = '2013-08-19' -- current day
where o.status = 2
Related
I have the following scenario. i have three tables (users, sales, sales_details) Users to Sales is a 1 to 1 relationship and sales to sales_details is 1 to many.
I am running a query where I get all the sales for each user by joining all 3 tables without any issue.
Query looks something like this
SELECT s.month as month,u.name as name, s.year as year, s.date as date,sum(sd.qty) as qty,sum(sd.qty*sd.value) as value,s.id as id,sum(sd.stock) as stock,s.currency as currency,s.user as user
FROM sales as s
left join sales_details as sd on s.id = sd.Sales
inner join users as u on s.user = u.Id
group by s.Id
What I want to do now is add an extra field in my query which will be a subquery.
SELECT SUM(total) AS total_yearly
FROM (
SELECT sum(qty) as total
FROM sales
left join sales_details on sales.Id = sales_details.Sales
WHERE ((month <= MONTH(NOW()) and year = YEAR(NOW()))
or (month >= MONTH(Date_add(Now(),interval - 12 month)) and year = YEAR(Date_add(Now(),interval - 12 month))))
and User = **ID OF USER** ) as sub
This query on its own gives me the sales for the user for the past 12 months while the original query does it per month. I know that the result will be the same for each user but i need it for other calculations.
My problem is how I will join the 2 queries so that the subquery will read the user id from the original one.
Thanks in advance!
Group the second query by user, and then join it with the original query.
SELECT s.month as month,u.name as name, s.year as year, s.date as date,
sum(sd.qty) as qty,sum(sd.qty*sd.value) as value,s.id as id,
sum(sd.stock) as stock,s.currency as currency,s.user as user,
us.total
FROM sales as s
left join sales_details as sd on s.id = sd.Sales
inner join users as u on s.user = u.Id
inner join (
SELECT User, sum(qty) as total
FROM sales
left join sales_details on sales.Id = sales_details.Sales
WHERE ((month <= MONTH(NOW()) and year = YEAR(NOW()))
or (month >= MONTH(Date_add(Now(),interval - 12 month)) and year = YEAR(Date_add(Now(),interval - 12 month)))))
GROUP BY User) AS us ON s.user = us.user
group by s.Id
I have 2 tables, restaurants and orders, orders table have restaurant_id, status and date fields, each day is a separate line in orders table.
I need to filter the restaurants and show only the restaurants that have at least one reservation for some date range, but I have to show it on a calendar, it should look like a list of restaurants with information.
Smth like this
So, it means that if at least one day with reserved status condition is satisfied in that date range, all the orders for that date range for that restaurant should be fetched as well.
I can not make a usual inner join,
SELECT r.`id`, r.`name`, o.`date`, o.`status`
FROM restaurants r
INNER JOIN orders o ON r.id = o.restaurant_id AND o.date BETWEEN '2013-08-10' AND '2013-08-31'
AND status = 'reserved'
because, in this case, for example, I will not have the order information for August 31, for restaurant2, because though it is in date rage from 10 - 31, but its status is 'closed'.
So, I am thinking to make a left join like this
SELECT r.`id`, r.`name`, o.`date`, o.`status`, o.`id` order_id
FROM restaurants r
LEFT JOIN orders o ON r.id = o.restaurant_id AND
o.date BETWEEN '2013-08-10' AND '2013-08-31'
WHERE o.`id` IS NOT NULL
But I need to also add one condition to ensure that there is at least one row with order's status = 'reserved', I tried to add where clause like COUNT(o.status = 1) > 0 but it gives an error.
THanks
I think the best way to achieve this (assuming things like 'N/A' and 'reserved' are stored in the orders table is to join to all orders in the first instance, and then use a second join to limit it to only restaurants that have a reservation within that period:
SELECT r.`id`, r.`name`, o.`date`, o.`status`, o.`id` order_id
FROM restaurants r
INNER JOIN orders o
ON r.id = o.restaurant_id
AND o.date BETWEEN '2013-08-10' AND '2013-08-31'
INNER JOIN
( SELECT DISTINCT o2.Restaurant_ID
FROM orders o2
WHERE o2.date BETWEEN '2013-08-10' AND '2013-08-31'
AND o2.Status = 'Reserved'
) o2
ON r.id = o2.restaurant_id;
Example on SQL Fiddle
I have a query like this:
SELECT
oh.date_added AS date_shipped,
o.date_added
FROM
".DB_PREFIX."order o , ".DB_PREFIX."order_history oh
WHERE
o.order_id = oh.order_id
AND oh.order_status_id = 3
What I want to do is only show results if there are X or more rows with a particular date.
So if X=5 there are three entries from the 2013-04-01, then they won't show, but if there are nine entries (or anything >= 5) from 2013-04-02 then these results will be included in the query.
Once the requirements are met I would like the query to limit to that one group of rows from the matching date.
Does anyone know how I can achieve this?
You can add nested SELECT to count these:
SELECT
oh.date_added AS date_shipped,
o.date_added
FROM
".DB_PREFIX."order o , ".DB_PREFIX."order_history oh
WHERE
o.order_id = oh.order_id
AND oh.order_status_id = 3
AND (SELECT COUNT(*) FROM ".DB_PREFIX."order o2
WHERE o2.date_added>"2013-04-01") > 5
Or join a table on itself, along the lines
SELECT
o.date,
COUNT(*) cnt
FROM
order o
JOIN order o2 ON o2.date = o.date AND o2.id != o.id
WHERE
your conditions
GROUP BY o2.id
HAVING cnt > 5
I need help writing a MySQL query. So far, none of the questions out there seem to fit my needs.
I have an order table and an order_log table. In the order_log table I make a record every time an order's status is changed. I need to display a list of the most recent status changes from the order_log table. The query I'm currently using does a JOIN on the two tables and grabs everything where order.status = order_log.status.
The problem with this is that some times an order will pass through the same status more than once. When that occurs, my query grabs every entry in the order_log table for that order and that status, but I only want the most recent log.
I tried writing a new JOIN query to grab the Max of the order_log date entry, but it's only returning 1 entry. This is what I have.
SELECT *
FROM order_status_log AS l
JOIN orders AS o ON ( l.order_id = o.id )
WHERE l.status = o.status
AND l.date = (
SELECT MAX( date )
FROM order_status_log l2
JOIN orders AS o2 ON ( l2.order_id = o2.id )
)
Any ideas?
there are many ways to do it, one is to have a separate subquery the gets the latest entry of each record: order_ID.
The result of the subquery is then joined back with the original table but has multiple conditions: that it matches the order_ID and also the latest date.
SELECT a.*, b.*
FROM `order` a
INNER JOIN order_log b
ON a.id = b.order_ID
INNER JOIN
(
SELECT order_ID, MAX(date) max_date
FROM order_log
GROUP BY order_ID
) c on b.order_ID = c.order_ID AND
b.date = c.max_date
That may help;
select olg.column1,o.column2,max(olg.date) from --You can add other columns as well
order_status_log olg
join orders o
on olg.id = o.order_id
group by olg.column1,o.column2
I can find the total number of customers with at least 5 orders using an SQL COUNT with subquery:
SELECT COUNT(*) FROM (
SELECT c.id FROM customers as c
INNER JOIN orders as o ON c.id = o.customer_id
GROUP BY c.id
HAVING COUNT(o.id) >= 5
) as temp
However I'd like to know how to achieve the same thing using the Rails active record query interface, if possible.
I have the code:
total_count = Customer.joins("INNER JOIN orders ON customers.id = orders.customer_id").group("customers.id").having("COUNT(orders.id) >= 5").count
But that results in a hash map of the customer id and number of orders, because the SQL that is generated looks like:
SELECT COUNT(*) AS count_all, customers.id AS customers_id FROM `customers` INNER JOIN orders ON customers.id = orders.customer_id GROUP BY customers.id HAVING COUNT(orders.id) >= 5
Is there another way to achieve what I'm aiming for using Rails conventions? Or should I just build the raw query?
You would need to join if you wanted some other info from customers, like their names or something like that. If count is all that you want just do a simple query on orders table:
SELECT * FROM orders
GROUP BY customer_id
HAVING COUNT(customer_id) >= 5
and count rows in the result set.