Filter Data By month Mysql - php

$listSQL = "SELECT op.name as prodname,count(*) total
FROM oc_order_product op
INNER JOIN oc_order o ON op.order_id = o.order_id
INNER JOIN oc_product_to_category p2c ON op.product_id = p2c.product_id
INNER JOIN oc_category_description cd ON cd.category_id = p2c.category_id ";
$listSQL = $listSQL."where lower(cd.name) LIKE '%".$category_name."%'
AND YEAR(o.date_added) = '".$StartDate."'
AND o.order_status_id > '0' ";
$listSQL = $listSQL."GROUP BY op.name ORDER BY o.date_added ASC";
I have this query where i am displaying product names and count by year.
I want to display Product name, and for each product, show month and count for that month for that particular year.
for example for year 2015, show all 12 months and under which show count of products for that month.
Thanks

Your original query looks pretty close, but using non-grouped, non-aggregated fields "outside" a group by is usually not a good idea unless they came from a table whose full primary key was part of the group by list. That said, this should give you what you want.
SELECT op.name AS prodname
, YEAR(o.date_added) AS oYear
, MONTH(o.date_added) AS oMonth
, COUNT(DISTINCT o.order_id) AS numOfOrders
FROM ...
GROUP BY prodname, oYear, oMonth
ORDER BY prodname, oYear, oMonth
;
[...] being your original FROM and WHERE

Related

Order products by sales within 30 days followed by those without sales

I'm trying to fetch a list of products ordered by the sold quantity within the last 30 days.
How would I make the following query also order by the sold quantity in the last 30 days and having them followed by the products that have not sold anything in those 30 days?
I need those with a sale within the last 30 days first and then the products without any sales after.
The field with the sale date is a datetime field called orders.sold_time
This is my current query:
SELECT pd.products_id AS id, pd.products_name AS name
FROM products_description pd
LEFT JOIN products ON pd.products_id = products.products_id
LEFT JOIN orders_products ON pd.products_id = orders_products.products_id
LEFT JOIN orders ON orders_products.orders_id = orders.orders_id
WHERE pd.c5_dataset = 'DAT'
AND products.products_status =1
AND pd.language_id =4
AND NOT EXISTS (
SELECT 1
FROM products_description
WHERE products_id = pd.products_id
AND language_id = 10
)
AND orders_total.class = 'ot_total'
GROUP BY pd.products_id
ORDER BY count( orders_products.products_quantity ) DESC
You can use a case when expression for that. The expression that gives you the sold quantity in the last 30 days is:
sum(case when orders.sold_time >= date_add(curdate(), interval -30 day)
then orders_products.products_quantity
end)
You can put this in the order by clause, and then you should decide what to order the articles by that have no sales in the last 30 days. This could for instance be the all-time sold quantity.
I would also use aliases for all your tables (like you did for the first one). So o for orders, op for orders_products.
So then your order by would look like:
order by sum(case when o.sold_time >= date_add(curdate(), interval -30 day)
then op.products_quantity
end),
sum(op.products_quantity)
To check the results, it would be good to also add those two expressions to the select list.
Some notes about the SQL:
As you have a non-null condition on products.products_status (=1) there is no good reason to use LEFT JOIN products. Instead use the more efficient INNER JOIN.
You would probably gain on efficiency if you would replace the NOT EXISTS condition with an INNER JOIN clause:
INNER JOIN products_description p2
ON p2.products_id = pd.products_id
AND p2.language_id = 10
provided there can be at most one description per product and language.

Using OR, AND operator in single query

I am trying to list the records which meets my condition. As ii am using AND and OR operator together i am not getting the exact report. Here is my query
SELECT o.sales_order_id AS SID, o.reference, o.status, o.last_modified, sol.sales_order_id, sol.item, sol.quantity, sol.selling_price, sol.discount, sol.tax, SUM(sol.tax_amount) AS Tamt, SUM(sol.total) as Total, i.iid, GROUP_CONCAT(DISTINCT i.name) AS iname, l.company, t.tax_id, t.name as tname, t.rate from orders o INNER JOIN before_order_line_items sol ON o.sales_order_id = sol.sales_order_id INNER JOIN leads l ON o.company_id=l.id INNER JOIN items i ON sol.item=i.iid INNER JOIN taxes t ON sol.tax=t.tax_id WHERE o.order_quote='Order' AND o.authorise='Yes' OR o.assigned_to=6 OR o.user_id=6 GROUP BY o.sales_order_id ORDER BY o.sales_order_id DESC
I am storing both orders and quotations in single table Orders, for orders i store it as Order in order_quote column, for Quotations it is Quote
It is not checking order_quote='Order' condition, it displays both orders and quotations.
if i remove OR o.assigned_to=6 OR o.user_id=6 , it gives proper result.
I tried using DISTINCT like this
SELECT DISTINCT o.order_quote=`Order`, .....
But does't work.
UPDATED
SELECT o.sales_order_id AS SID, o.reference, o.status, o.last_modified, sol.sales_order_id, sol.item, sol.quantity, sol.selling_price, sol.discount, sol.tax, SUM(sol.tax_amount) AS Tamt, SUM(sol.total) as Total, i.iid, GROUP_CONCAT(DISTINCT i.name) AS iname, l.company, t.tax_id, t.name as tname, t.rate from orders o INNER JOIN before_order_line_items sol ON o.sales_order_id = sol.sales_order_id INNER JOIN leads l ON o.company_id=l.id INNER JOIN items i ON sol.item=i.iid INNER JOIN taxes t ON sol.tax=t.tax_id WHERE (o.order_quote='Order' AND o.authorise='Yes') AND (o.assigned_to=6 OR o.user_id=6) GROUP BY o.sales_order_id ORDER BY o.sales_order_id DESC
You need to use parentheses. I'm not sure exactly how, but your current where clause is interpreted as:
WHERE (o.order_quote = 'Order' AND o.authorise = 'Yes') OR
(o.assigned_to = 6) OR
(o.user_id = 6)
I would guess that you want something like this:
WHERE (o.order_quote = 'Order' AND o.authorise = 'Yes') AND
(o.assigned_to = 6 OR o.user_id = 6)
But that is mere speculation.
Or perhaps:
WHERE (o.order_quote = 'Order' AND
(o.authorise = 'Yes' OR o.assigned_to = 6 OR o.user_id = 6)

PHP Mysql Joins and Where Clause

I need help on below statement. I need to put WHERE items.IID = 8 so that it shows only details pertaining to IID number 8. But when I use WHERE items.IID = 8, it is not working. I have to use this type of join as I want to do Sum and Count of some fields. There are 3 tables. 1st is items, 2nd is ItemPurchaseHistory and 3rd is ItemIssuedHistory.
SELECT items.IID, items.ItemName, ItemPurchaseHistorySum.SumOfUnitsPurchased, ItemPurchaseHistorySum.SumOfCost,
ItemPurchaseHistoryCount.CountOfUnitsPurchased,
ItemIssuedHistorySum.SumOfUnitsIssued
FROM items
LEFT JOIN (SELECT IID, SUM(UnitsPurchased) AS SumOfUnitsPurchased, SUM(Cost) AS SumOfCost
FROM ItemPurchaseHistory
GROUP BY IID) ItemPurchaseHistorySum ON ItemPurchaseHistorySum.IID = items.IID
LEFT JOIN (SELECT IID, Count(UnitsPurchased) AS CountOfUnitsPurchased
FROM ItemPurchaseHistory
GROUP BY IID) ItemPurchaseHistoryCount ON ItemPurchaseHistoryCount.IID = items.IID
LEFT JOIN (SELECT IID, SUM(UnitsIssued) AS SumOfUnitsIssued
FROM ItemIssuedHistory
GROUP BY IID) ItemIssuedHistorySum ON ItemIssuedHistorySum.IID = items.IID
WHERE item.IID = $_GET['id']
ORDER BY items.IID ASC

Order by slow query in mysql

i am using this query to fetching products.the product table has 302,716 rows.it is taking too much time to execute around 2-3 minutes.but when i removed order by it takes less time.
SELECT DISTINCT
product.ProductID,
company.CompanyName
FROM
product
INNER JOIN company
ON company.CompanyID = product.CompanyID
LEFT JOIN company_csv_data
ON company.CompanyID = company_csv_data.CompanyID
LEFT JOIN productcategory
ON product.ProductID = productcategory.ProductID
LEFT JOIN category
ON category.CategoryID = productcategory.CategoryID
LEFT JOIN supplier
ON product.supplier = supplier.id
LEFT JOIN template_vouchers tm
ON product.ProductID = tm.voucher_id
WHERE company.turn_on = 1
AND product.ProductEndDate >= CURRENT_DATE
AND turn_off = 1
GROUP BY product.ProductID
ORDER BY clicks DESC,
product.CodeOpen DESC,
product.Online,
product.EntryDate DESC
LIMIT 0, 15
You could improve the query's speed/performance by creating indexes for the columns in the select and where clauses (this will slow down insert, delete and update statements..)

Getting all different values but not duplicates from multiple records

I have the following SQL:
SELECT o.order_id, ol.product_manufacturer
FROM orders o
INNER JOIN order_lines ol
ON o.order_id = ol.order_id
WHERE o.deadline_time > UNIX_TIMESTAMP()
I also have these tables:
orders:
order_id, somefield, somefield, somefield...
order_lines:
id, order_id, product_manufacturer, somefield, somefield...
I want to get all orders where deadline hasn't passed and group them by product_manufacturer, but if an order has three order lines, that all have the product_manufacturer id, then it should only return the id ones. If it has the two order lines with different product_manufacturer id, then it should return the id twice and so on.
I'm using PHP and I would like to end up with an array like this:
$group[manufacturer_id] = array(order_id, order_id, order_id);
EDIT: Actually I want it to return manufacturer_id = 999, if there are multiple manufacturer ids in an order. Sorry for the mistake.
EDIT2: I'm making a listing of all orders, but I have to list them by their manufacturer. Like so:
SONY
Order 1
Order 2
Order 16
Order 99
PROSONIC
Order 3
Order 88
Order 98
Later it should be possible to search, so I will have to make something like WHERE ol.product_name LIKE '%$query', but I will add that later on, when it works.
SELECT o.order_id,group_concat(distinct(ol.product_manufacturer )) as manufacturer
FROM orders o
INNER JOIN order_lines ol
ON o.order_id = ol.order_id
WHERE o.deadline_time > UNIX_TIMESTAMP()
group by o.order_id
This will return
Order_id manufacturer
1 sony, panasonic
2 sony
SELECT o.order_id,
CASE WHEN count(distinct(ol.product_manufacturer )) >1
THEN '999' ELSE product_manufacturer END as manufacturerid
FROM orders o
INNER JOIN order_lines ol
ON o.order_id = ol.order_id
WHERE o.deadline_time > UNIX_TIMESTAMP()
group by o.order_id
This will return
Order_id manufacturerid
1 999
2 sony
As far as I can see you cannot get that form of output from a single SQL command.
I suggest you to get SELECT DISTINCT product_manufacturer FROM order_lines and then search from all orders where deadline hasn't passed for each product_manufacturer.
For ex:
SELECT o.order_id FROM orders o, order_lines ol
WHERE o.deadline_time > UNIX_TIMESTAMP()
AND ol.product_manufacturer='$pro_man'
#UlrikMcArdle
why isn't the first query with ORDER BY what you are looking for?
SELECT o.order_id, ol.product_manufacturer
FROM orders o
INNER JOIN order_lines ol ON o.order_id = ol.order_id
WHERE o.deadline_time > UNIX_TIMESTAMP()
ORDER ol.product_manufacturer, o.order_id
SELECT ol.product_manufacturer
FROM orders o
INNER JOIN order_lines ol
ON o.order_id = ol.order_id
WHERE o.deadline_time > UNIX_TIMESTAMP()
GROUP BY ol.product_manufacturer
you can use some sort of UDF to concat all the order_id for the manufacture.
Click here for similar UDF

Categories