Query grouped by month on multiple JOINs - mysql

Ok, I'm grouping a query by month so I get a record for each month of the year, but I need to figure out how to do this: basically grouping by month on two different JOIN statements. I'm trying to get the count, or sum, of quantities in each child table if possible in one query. I could just loop through in php, but I'm trying to find a way to do in mysql.
Here's a sample
SELECT SUM(purchase_quantity),SUM(sales_quantity)
FROM products p
INNER JOIN purchase_order_lines sl ON pl.product_id = p.id
INNER JOIN purchase_orders po ON pl.purchase_order_id = po.id
INNER JOIN sales_order_lines sl ON sl.product_id = p.id
INNER JOIN sales_orders so ON sl.sales_order_id = so.id
GROUP BY YEAR(so.posted & po.posted), MONTH(so.posted & po.posted)
I know there's no way this would work, and the logic is ridiculous, and this isn't exactly the structure of my database, but just an idea of how things are linked and wwhat I'm trying to do. I'm thinking it would have to be done with subqueries in the SELECT statement, but I haven't come up with anything yet. I'll keep thinking about it, but if anyone has any ideas, that would be awesome.

because your grouping your result, you will get a count of one. why don't you try running a separate statement that will count the result and a separate statement to group it.

Related

Why does COUNT(*) does the same as COUNT(column) in this query?

I am finishing a SQL course and they have a query example that I don't quite understand.
I have
these tables
and I need to get how many 'etiquetas' (tags in Spanish), are in each post, so they have this solution:
SELECT posts.titulo, COUNT(*) num_etiquetas
FROM posts
INNER JOIN posts_etiquetas ON posts.id = posts_etiquetas.post_id
INNER JOIN etiquetas ON etiquetas.id = posts_etiquetas.etiqueta_id
GROUP BY posts.id
ORDER BY num_etiquetas DESC;
I have been trying to understand this query and two questions came up:
Why COUNT(asterisk) does the same as COUNT(etiquetas.nombre)? For me only the latter makes sense, I don't quite understand why COUNT(asterisk) works in the given solution, isn't COUNT(*) supposed to count the total number of rows? maybe the issue is that I don't really understand how GROUP BY really works.
Why does deleting this line doesn't change the result? What is its use in the original solution?
INNER JOIN etiquetas ON etiquetas.id = posts_etiquetas.etiqueta_id

MySql: order by along with group by - performance

I have the performance problem with query that have order by and group by. I have checked similar problems on SO but I did not find the solution to this:(
I have something like this in my db schema:
pattern has many pattern_file belongs to project_template which belongs to project
Now I want to get projects filtered by some data(additional tables that I join) and want to get the result ordered for example by projects.priority and grouped by patterns.id. I have tried many things and to get the desired result I've figured out this query:
SELECT DISTINCT `projects`.* FROM `projects`
INNER JOIN `project_templates` ON `project_templates`.`project_id` = `projects`.`id`
INNER JOIN `pattern_files` ON `pattern_files`.`id` = `project_templates`.`pattern_file_id`
INNER JOIN `patterns` ON `patterns`.`id` = `pattern_files`.`pattern_id`
...[ truncated ]
INNER JOIN (SELECT DISTINCT projects.id FROM `projects` INNER JOIN `project_templates` ON `project_templates`.`project_id` = `projects`.`id`
INNER JOIN `pattern_files` ON `pattern_files`.`id` = `project_templates`.`pattern_file_id`
INNER JOIN `patterns` ON `patterns`.`id` = `pattern_files`.`pattern_id`
...[ truncated ]
WHERE [here my conditions] ORDER BY [here my order]) P
ON P.id = projects.id
WHERE [here my conditions]
GROUP BY patterns.id
ORDER BY [here my order]
From my research I have to INNER JOIN with subquery to conquer the problem "ORDER BY before GROUPing BY" => then I have put the same conditions on the outer query for performance purpose. The order by I had to use again in the outer query too, otherwise the result will be sorted by default.
Now there is real performance problem as I have about 6k projects and when I run this query without any conditions it takes about 15s :/ When I narrow the result by specify the conditions the time drastically dropped down. I've found somewhere that the subquery is run for every outer query row result which could be true when you watch at the execution time :/
Could you please give some advice how I can optimize the query? I do not work much with sql so maybe I do it from the wrong side from the very beginning?
P.S. I have tried WHERE projects.id IN (Select project.id FROM projects ....) and that discarded the performance issue but also discarded the ORDER BY before GROUPing BY
EDIT.
I want to retrieve list of projects, but I want also to filter it and order, and finally I want to get patterns.id unique(that is why I use the group by).
order by in your inner query (p) doesn't make sense (any inner sort will only
have an arbitrary effect).
#Solarflare Unfortunately it does. group by will take first row from grouped result. It preserve the order for join. Well, I believe that it is specific to MySql. Furthermore to keep the order from subquery I could use ORDER BY NULL in outer query :-)
Also, select projects.* ... group by pattern.id is fishy (although MySQL, in contrast to every other dbms, allows you to do this)
so we can assume I retrieve only projects.id, but from docs:
MySQL extends the use of GROUP BY to permit selecting fields that are not mentioned in the GROUP BY clause

Returning distinct records based on left join

I'm having some trouble formulating a complex SQL query. I'm getting the result I'm looking for and the performance is fine but whenever I try to grab distinct rows for my LEFT JOIN of product_groups, I'm either hitting some performance issues or getting incorrect results.
Here's my query:
SELECT
pl.name, pl.description,
p.rows, p.columns,
pr.sku,
m.filename, m.ext, m.type,
ptg.product_group_id AS group,
FROM
product_region AS pr
INNER JOIN
products AS p ON (p.product_id = pr.product_id)
INNER JOIN
media AS m ON (p.media = m.media_id)
INNER JOIN
product_language AS pl ON (p.product_id = pl.product_id)
LEFT JOIN
products_groups AS ptg ON (ptg.product_id = pr.product_id)
WHERE
(pl.lang = :lang) AND
(pr.region = :region) AND
(pt.product_id = p.product_id)
GROUP BY
p.product_id
LIMIT
:offset, :limit
The result I'm being given is correct however I want only distinct rows returned for "group". For example I'm getting many results back that have the same "group" value but I only want the first row to show and the following records that have the same group value to be left out.
I tried GROUP BY group and DISTINCT but it gives me incorrect results. Also note that group can come back as NULL and I don't want those rows to be effected.
Thanks in advance.
I worked out a solution an hour after posting this. My goal was to group by product_group_id first and then the individual product_id. The requirement was that I would eliminate product duplicates and have ONE product represent the group set.
I ended up using COALESCE(ptg.product_group_id, p.product_id). This accounts for the fact that most of my group IDs were null except for a few dispersed products. In using COALESCE I'm first grouping by the group ID, if that value is null it ignores the group and collects by product_id.

Join Orders, Staff's first and last name, item and location MySQL

Join Orders, Staff's first and last name, item and location into one so I can export the content into an Excel spreadsheet.
SELECT orders.order_id, staff.staff_id, staff.first_name, staff.last_name, items.name, locations.address1, locations.address2, locations.state, locations.zip_code, orders.created_at
FROM orders
INNER JOIN staff
ON orders.staff_id = staff.staff_id
INNER JOIN items
ON orders.item_id = items.item_id
INNER JOIN location_staff
ON location_staff.staff_id = staff.staff_id
INNER JOIN locations
ON location_staff.loc_id = location.loc_id
I am trying to gather this information to put into an excel document but my query is not returning any results. Any help would be appreciated.
Here is An ERD diagram for further understanding
https://www.dropbox.com/s/7inma4s42xq5t4a/ERD.jpg
(Location_staff_link was shortened when created to location_staff)
jsut remove the extra tables in your FROM clause,
SELECT orders.order_id,
staff.staff_id,
staff.first_name,
staff.last_name,
items.name,
orders.created_at
FROM orders
INNER JOIN staff
ON orders.staff_id = staff.staff_id
INNER JOIN items
ON orders.item_id = items.item_id
INNER JOIN locations
ON location.staff_id = staff.staff_id
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
Nothing in your query looks bad, so here is what I suggest to find the answer in this sort of case.
First reduce to the bare minimum of the first join and change the fields to select * (temporarily, you can go back to the real fields as soon as you find the issue) so you can se all the data.
Do you get records, then add in any where clauses on the tables in that join. Do you still get records?
Then add in each join and each where clause one at a time until you find the one where the records disappear. This will tell you what you need to do to fix it.
Often in a case like this where no records are returned, one of the joins needs to be a left join or there is no data that meets the terms of the where clauses or one of the joins is improperly defined. And sometimes, there is a problem in that your database does not have the data you were expecting it to have. But first you have to use the process above to diagnose where the problem is.

Left outer join and sum issue

I need a query. I'm trying to sum of one field with joined tables. Some records not in second table. So this records sum should be zero. But the query only sum the records which are in the second table.
select s.*,sum(sd.fiyat) as konak from fuar_sozlesme1 s
left outer join fuar_sozlesme1_detay sd on (sd.sozlesme_id = s.id)
------EDIT-------
I added group by into the query and solved my problem. Here is the new ;
select s.*,sum(sd.fiyat) as konak from fuar_sozlesme1 s
left outer join fuar_sozlesme1_detay sd on (sd.sozlesme_id = s.id)
group by sd.sozlesme_id
I thinik you need to use IFNULL(sd.fiyat,0) instead of sd.fiyat to get zeros for the NULL values coming from the second table because of the LEFT JOIN like so:
SELECT s.*, SUM(IFNULL(sd.fiyat, 0)) as konak
FROM fuar_sozlesme1 s
LEFT OUTER JOIN fuar_sozlesme1_detay sd ON sd.sozlesme_id = s.id
GROUP BY s.someFields
Here is a simple example, you may help: http://sqlfiddle.com/#!2/41481/1
This is an old thread, but I spent a couple of hours trying to solve the same issue.
My query has two joins, a filter and a SUM function. I'm no SQL expert, but this helped me achieve the desired result of still showing a result even if the joined table had no rows to sum.
The key for me in order to show results even if the sum was totaling nothing, was the GROUP BY. I'm still not 100% sure why.
The two types of joins were chosen based on this article - MySQL Multiple Joins in one query?
SELECT registrations.reg_active, registrations.team_id, registrations.area_id, registrations.option_id, registrations.reg_fund_goal, registrations.reg_type, registrations.reg_fee_paid, registrations.reg_has_avatar, users.user_name, users.user_email, users.user_phone, users.user_zip, users.user_age, users.user_gender, users.user_active, SUM(IFNULL(donations.donation_amount,0)) as amt from registrations
INNER JOIN `users`
ON registrations.user_id = users.user_id
AND registrations.event_id = :event_id
LEFT OUTER JOIN `donations`
ON registrations.reg_id = donations.reg_id
GROUP BY donations.reg_id
ORDER BY users.user_name ASC