Join2 tables and group by date - php

I want to sum all win_ticket and divide it to the sum of all sold_ticket from 2 tables to get the percentage and then group it by date.
This is not working at all.....
sold_ticket
customer_winner
$query = "SELECT
sold_ticket.date, sold_ticket.sold_ticket,
SUM(sold_ticket) AS sold_ticket,
customer_winner.date, customer_winner.win_ticket,
SUM(win_ticket) AS lottery_win
FROM sold_ticket
INNER JOIN customer_winner
ON sold_ticket.date = customer_winner.date
GROUP BY date
";

need to grouping sold_ticket.date or customer_winner.date or both of them.
try this
SELECT sold_ticket.date,
SUM (sold_ticket) AS sold_ticket,
SUM(customer_winner.win_ticket),
SUM (win_ticket) AS lottery_win
FROM sold_ticket
INNER JOIN customer_winner ON sold_ticket.date= customer_winner.date
GROUP BY sold_ticket.date;

Related

Perform calculating on each result of a MySQL search

To calculate a total amount for an order, I go to the articles table, and calculate the sum of the articles for this order.
Here is my code:
SELECT orders.*,
ROUND(SUM(`orders_article_updated_quantity` * (`orders_article_price` * (100 - orders_article_rate)/100)), 2) AS 'order_Total'
FROM orders JOIN orders_articles
ON orders.order_id = orders_articles.orders_article_id_order
WHERE oreder_id = '" . $order['order_id'] . "'
This code is working for an order, and I got a good result.
Now I want to do this for a list of orders, or all orders. So I deleted the "WHERE" from my request. And I get only one result, with the sum of all orders.
For each result (order), I want the sum of its own articles.
You need aggregation for this. Consider adding a group by clause to the query, like so:
SELECT
o.*,
ROUND(SUM(orders_article_updated_quantity * orders_article_price * (1 - orders_article_rate/100)), 2) AS order_Total
FROM orders o
INNER JOIN orders_articles oa ON ao.orders_article_id_order = o.order_id
GROUP BY o.order_id
Note that you should prefix each column in the query with the table they belong to - that's not the case for the column within the SUM(), which creates ambiguity.
Another option is a correlated subquery (this allows orders without any article):
SELECT
o.*,
(
SELECT ROUND(SUM(orders_article_updated_quantity * orders_article_price * (1 - orders_article_rate/100)), 2)
FROM orders_articles oa
WHERE ao.orders_article_id_order = o.order_id
) AS order_Total
FROM orders o

Sum columns on different tables and multiply by value of a column on another table

I need to compute employees' monthly salaries based on meetings attended, deductions and bonuses given;
Employees have different pay per meeting based on their job position.
The solution is:
salary = (Pay_per_minute * meetings_attended) + bonuses - deductions ;
I have four tables:
Jobs: Id, title, pay_per_meeting
Employees: Id, Name, job_id
Bonuses: Id, amount, employee_id, date
Deductions: Id, amount, employee_id, date
Meetings: Id, employee_id, date
SELECT
COUNT(meetings.employee_id) as meetings_attended,
COUNT(deductions.amount) as debt,
COUNT(bonuses.amount) bonus,
(SELECT jobs.pay_per_attendance from jobs where jobs.id = (select job_id from employees where id=meetings.employee_id)) as pay,
((meetings_attended * pay) + bonus - debt) as salary
FROM meetings
JOIN deductions ON deductions.employee_id = meetings.employee_id
JOIN bonuses ON bonuses.employee_id = meetings.employee_id
WHERE meetings.employee_id = 1
GROUP BY MONTH(meetings.date), MONTH(deductions.date), MONTH(bonuses.date)
The above query returns many incorrect values whenever i remove the salary line but gives error of unknown column pay, meetings_attended, debt and bonus, am sure something is wrong with the grouping but i can't just see it.
You can't refer to column aliases in the same select list as they're defined, you need to refer to the underlying column. And a subquery can't access an aggregate calculated in the main query. You need to repeat the aggregate expression, or move everything into a subquery and do the calculation with it in an outer query.
Also, all your COUNT() expressions are going to return the same thing, since they're just counting rows (I assume none of the values can be NULL). You probably want COUNT(DISTINCT <column>) to get different counts, and you need to use a column that's unique, so they should be the primary key column, e.g. COUNT(DISTINCT deductions.id).
Another problem is that when you try to sum and count values when you have multiple joins, you end up with a result that's too high, because rows get duplicated in the cross product of all the tables. See Join tables with SUM issue in MYSQL. The solution is to calculate the sums from each table in subqueries.
SELECT m.month, m.meetings_attended, d.debt, b.bonus,
m.meetings_attended * j.pay_per_meeting + b.amount - d.amount AS salary
FROM (
SELECT MONTH(date) AS month, COUNT(*) AS meetings_attended
FROM meetings
WHERE employee_id = 1
GROUP BY month) AS m
JOIN (
SELECT MONTH(date) AS month, COUNT(*) AS bonus, SUM(amount) AS amount
FROM bonuses
WHERE employee_id = 1
GROUP BY month) AS b ON m.month = b.month
JOIN (
SELECT MONTH(date) AS month, COUNT(*) AS debt, SUM(amount) AS amount
FROM deductions
WHERE employee_id = 1
GROUP BY month) AS d ON m.month = d.month
CROSS JOIN employees AS e
JOIN jobs AS j ON j.id = e.job_id
WHERE e.employee_id = 1

How can I Sum / Group By the results of this table

I have a table of hours which looks like :
I want to sum the hours_spent results for this week only and group the results by the created_by person. I have this query which returns the correct data for showing only results in this week :
SELECT staff_id, first_name, last_name, date_entered, `hours_spent` as total_hours FROM hours LEFT JOIN staff ON hours.created_by = staff.staff_id where yearweek(`date_entered`) = yearweek(curdate());
But when I add the SUM(hours_spent) as total_hours and group by staff_id like the example below I get 0 results.
SELECT staff_id, date_entered, first_name, last_name, SUM(`hours_spent`) as total_hours FROM hours LEFT JOIN staff ON hours.created_by = staff.staff_id group by staff_id having yearweek(`date_entered`) = yearweek(curdate());
I'm assuming it's not working because the Having part of my statement doesn't return individual rows of dates so it breaks.
I feel like I am doing this the hard way. Should I be trying to run a second summing query on the results of the first query rather than combine it all into one (I was hoping for cleanliness). Or should I be using a subquery to filter out the dates that aren't this week then group the totals if so how could I accomplish this?
I got what I was expecting with :
SELECT staff.first_name,staff.last_name, sum(hours_spent)
FROM hours
LEFT JOIN staff ON hours.created_by = staff.staff_id
WHERE yearweek(date_entered,1) = (yearweek(curdate(),1)-1)
GROUP BY created_by

MySQL Need to show 0 when no value in right hand table of join, with cumulative

I have one table with a list of number of sales per month against product code and another with a list of months that can extend before or after the months that had a sale in. I need to results to show 0 sales if there were no sales in the month and for the cumulative to add this up. I have tried using case and if and getting it to put 0 if sales.sales was null but this did not work and I still just had blanks.
create table summary as (SELECT
q1.productid As productid,
q1.date AS Month_View,
q1.sales AS Monthly_Units_Sold,
(#runtot_sales := #runtot_sales + q1.sales) AS Cumulative_Sales
FROM
(SELECT
sales.productid,
dates.date,
if(sales.date is null,0,sales.sales) as sales
from
dates
left join sales on dates.date = sales.date
where
sales.productid = '$input1'
group by dates.date
ORDER BY date) AS q1);
";
Try COALESCE() function to return the first non-NULL value of a list Also see demo here
CREATE TABLE summary AS
(SELECT
q1.productid AS productid,
q1.date AS Month_View,
q1.sales AS Monthly_Units_Sold,
(
#runtot_sales := #runtot_sales + q1.sales
) AS Cumulative_Sales
FROM
(SELECT
sales.productid,
dates.date,
COALESCE(sales.sales, 0) AS sales
FROM
dates
LEFT JOIN sales
ON dates.date = sales.date
WHERE sales.productid = '$input1'
GROUP BY dates.date
ORDER BY DATE) AS q1) ;
MySQL COALESCE() function
You are misusing GROUP BY and therefore getting indeterminate results. See this: http://dev.mysql.com/doc/refman/5.5/en/group-by-extensions.html
If you're aggregating your items by product and date you probably want something like this.
SELECT sales.productid,
dates.date,
SUM(sales.sales) as sales
FROM dates
LEFT JOIN sales ON dates.date = sales.date
WHERE sales.productid = '$input1'
GROUP BY sales.productid, dates.date
ORDER BY /* i'm not sure what you're trying to do with the running total */
Note that SUM(sales.sales) handles the NULL values from your LEFT JOIN correctly. If the date doesn't join a sales row then sales.sales will be NULL.
If you're trying to do a month-by-month summary you need more logic than you have. See this writeup: http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/

mySQL AVG - A way to merge two results for AVG

I'm trying to get the average number of interactions on my metrics, but this query gets the average number of inteactions for those who DID interact (those in metricsActions are only there if they HAVE interacted, their metricsID still exists in metrics table).
So, I'm wondering how I can get the average of all those users. I can do two queries, but then how would I average with the two results? Is it possible to merge?
SELECT AVG(`instances`) FROM (SELECT m.`metricID`, COUNT(mc.`metricAction`) as `instances` FROM `metricActions` mc LEFT JOIN `metrics` m ON m.`metricID` = mc.`metricID` WHERE m.`clientID` = '10412' AND `type` = '2' AND GROUP BY mc.`metricID` ORDER BY `instances` DESC ) as `temp`
You should use the LEFT JOIN the other way around:
SELECT AVG(`instances`)
FROM (
SELECT m.`metricID`, COUNT(mc.`metricAction`) as `instances`
FROM `metrics` m
LEFT JOIN
`metricActions` mc
ON mc.`metricID` = m.`metricID`
AND mc.`type` = '2'
WHERE m.`clientID` = '10412'
GROUP BY
m.`metricID`
) as `temp`

Categories