Select where number of results is above x - mysql

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

Related

How to get unique records with join tables and without using group by

I want to get unique record from 2 tables without using Group By instead of i want to use DISTINCT because when i used group by it does not return last updated records.
I used following query with Group By.
SELECT au.id, o.order_id,o.payment_method, o.order_date,au.article_id FROM `orders` as o INNER JOIN austpost_api_response as au ON o.order_id = au.order_id where o.shipment_status = 1 AND au.active_status = 1 AND o.order_status = 0 group by o.order_id
ORDER BY `au`.`id` DESC
It's returns unique order_id but not getting last updated order_id
For example...
Order number 1212 has four article_id id 45,76,47,48 but once i used this with group by it's display unique order id but not getting 48 last updated record instead of it's return 45.
is it possible to get with DISTINCT keyword.
You can use row_number() function if your mysql version 8.0+
select * from
(
SELECT au.id, o.order_id,o.payment_method, o.order_date,au.article_id,row_number() over(partition by o.order_id order by o.order_date desc) as rn
FROM `orders` as o INNER JOIN austpost_api_response as au ON o.order_id = au.order_id where o.shipment_status = 1 AND au.active_status = 1 AND o.order_status = 0
)A where rn=1
OR You can try using correlated subquery
SELECT au.id, o.order_id,o.payment_method, o.order_date,au.article_id
FROM `orders` as o INNER JOIN austpost_api_response as au ON o.order_id = au.order_id
where o.shipment_status = 1 AND au.active_status = 1 AND o.order_status = 0 and o.order_date in
(
select max(o.order_date) from `orders` o1 where o.order_id = o1.order_id and o1.order_status = 0
)
If I understand correctly, you have multiple rows for the responses for each order -- and you want the most recent one per order.
You want to filter the data, not aggregate it. I think this does what you want:
SELECT au.id, o.order_id, o.payment_method, o.order_date, au.article_id
FROM orders o INNER JOIN
austpost_api_response au
ON o.order_id = au.order_id
WHERE o.shipment_status = 1 AND
au.active_status = 1 AND
o.order_status = 0 AND
au.id = (SELECT MAX(au2.id)
FROM austpost_api_response au2
WHERE au2.order_id = au.order_id AND
au2.active_status = 1
)
ORDER BY au.id DESC;

mysql "distinct query" from 3 table performs slow on big data

Here is three table, order, order_record, pay, with near 2300000 records.
there will be more than 1 record in pay table when giving 1 order_id, so I need to use DISTINCT to remove repeated result
now I need to get distinct data from those three table join on order_id, the example query sql below:
SELECT
DISTINCT (a.order_id)
a.order_id,a.user_id
b.boss_order_id,
c.pay_id,
FROM order a
LEFT JOIN order_record b ON a.order_id = b.order_id AND b.is_delete IN (0,1)
LEFT JOIN pay c ON a.order_id = c.order_id AND c.is_delete =0 WHERE 1=1 AND a.is_delete IN (0,1)
ORDER BY a.id DESC LIMIT 0, 10
this query will takes plenty of time.
then I change to use "GROUP BY":
SELECT
a.order_id,a.user_id
b.boss_order_id,
c.pay_id,
FROM order a
LEFT JOIN order_record b ON a.order_id = b.order_id AND b.is_delete IN (0,1)
LEFT JOIN pay c ON a.order_id = c.order_id AND c.is_delete =0 WHERE 1=1 AND a.is_delete IN (0,1)
GROUP BY a.order_id
ORDER BY a.id DESC LIMIT 0, 10
this time the query takes 122 seconds.
Is there any faster way to implement?
You are using a left join. Hence, you can do:
SELECT o.order_id, o.user_id, orr.boss_order_id, p.pay_id,
FROM (SELECT o.*
FROM order o
WHERE o.is_delete IN (0, 1)
ORDER BY o.id DESC
LIMIT 10
) o LEFT JOIN
order_record orr
ON o.order_id = orr.order_id AND
orr.is_delete IN (0, 1) LEFT JOIN
pay p
ON o.order_id = p.order_id AND
p.is_delete = 0
WHERE 1=1 AND o.is_delete IN (0, 1)
GROUP BY o.order_id
ORDER BY o.id DESC
LIMIT 0, 10
You are using GROUP BY incorrectly, because you have unaggregated columns in the SELECT that are not in the GROUP BY.
Another approach let a where clause do most the work:
select ...
from order
left join order_using using (order_id)
...
where
order.order_id < (select max(order_id) from orders order by order_id limit 10) ...
limit 10
The final limit 10 is weird though as you may get partial records from an order if you drop the group by. I.e. you probably want to drop it and and just put a limit orders table. With the group by means you will a random data from table b and c unless you use aggregate function to tell mysql which of the row values you want.

Change clear SQL to queryBuilder subquery

Order entity has OneToMany OrderStatsu so any order have many statuses and I want to find all orders where last status = x.
My query look like this (and work)
SELECT o.id, os.status_id FROM orders o
LEFT JOIN(
SELECT *
FROM order_status
GROUP BY orders_id DESC
) AS os
ON o.id = os.orders_id
But I want to get it as object.
First of all GROUP BY orders_id DESC is a wrong syntax. You can change your query like
SELECT o.id, os.status_id
FROM orders o
LEFT JOIN(SELECT status_id, orders_id,
GROUP_CONCAT(statuses ORDER BY statuses DESC) AS Status
FROM order_status
GROUP BY orders_id) os
ON o.id = os.orders_id
WHERE LEFT(os.Status) = 'X';

This query only returns one results , supposed to return two

This query is supposed to return two order_ids .. but only returning one , and the order_ids meet the conditions of the query ... what could be wrong ?
SELECT r.*
FROM products_to_products_extra_fields AS p
INNER JOIN orders_roster AS r ON p.products_id = r.products_id
INNER JOIN orders AS o on r.orders_id = o.orders_id
WHERE p.products_extra_fields_id = 14 AND
p.products_extra_fields_value between '2013-11-01' and '2013-11-30 23:59:59' AND
r.roster_status != 'Removed' AND
o.payment_method = 'Institutional Billing' AND
o.orders_status < 100001
GROUP BY o.orders_id
ORDER BY DECODE(o.cc_type, 'oFsAfHr7') ASC
Try:
SELECT DISTINCTROW r.* ...
Also, experiment with the GROUP BY clause, which may be causing the rows to collapse on orders_id.

Limiting results to a distinct column with SQL

I am attempting to get a list of items along with the order information for each item. An order always has at least 1 item associated with it. I want to limit this list to all of the items from 10 orders. As my query stands below, it gets 10 items. What is the best way to LIMIT this to 10 orders, while grabbing all of the items associated with these orders (be it 10 rows or 200 rows)?
SELECT o.*, i.*
FROM orders o, items i
WHERE i.order_id = o.id
LIMIT 0, 10
Much thanks!
Try using a subselect where you limit the orders first. In the outer select you then can fetch all items to these 10 orders.
SELECT o.*, i.*
FROM items i, (SELECT * FROM orders LIMIT 0, 10) o
WHERE i.order_id = o.id
SELECT oo.*, i.*
FROM (
SELECT *
FROM orders o
LIMIT 10
) oo , items i
WHERE i.order_id = oo.id
I don't know mysql but to take a guess
SELECT o.*, i.*
FROM orders o, items i
WHERE i.order_id = o.id and
o.id in (select o.id from orders o limit 0, 10)
Something like this should work:
SELECT o.*, i.*
FROM items i INNER JOIN orders o ON o.id = i.order_id
WHERE o.order_id IN (
SELECT o.id
FROM orders
LIMIT 0, 10
)
SELECT orders1.*, items.*
FROM
(select * from orders
LIMIT 10) AS orders1
LEFT JOIN items ON orders1.id = items.order_id;