I have a query that essentially should bring the total sales per day but I don't know what I'm doing wrong in the query that brings me all the sales without adding the days.
$ventasdia = DB::select('SELECT DATE_FORMAT(v.fecha_venta,"%d/%m/%Y") as dia, sum(v.monto) as totaldia from ventas v where v.id_estado_venta="2" group by v.fecha_venta order by
day(v.fecha_venta) desc limit 12');
This is what the query brings me:
As can be seen, the days are repeated and it does not add up per day.
You need to GROUP BY dia not by v.fecha_venta.
If you group by v.fetch_venta it groups by the datetime and this is probably different for every row.
Related
I am trying to achieve the Sum of Hours spent per day, where my mysql database has multiple logging records of every activity they perform (e.g; login, view, update, logout). What i am trying to do is SELECT (all records of a particular day) and find the difference in epoch time between the first and last entry giving me the 'Time Spent' for that period. Later add it by Month etc.
Database schema;
id, userid, time, action
**I can select the first and last entry from the query below:
**
SELECT
(SELECT time FROM log WHERE time(myDate) = DATE(NOW()) ORDER BY time LIMIT 1) as 'first',
(SELECT column FROM table WHERE time(myDate) = DATE(NOW()) ORDER BY time DESC LIMIT 1) as 'last'
But i am guessing a cross join or SUM for all these have to happen. Some guidance would be much appreciated.
In my application, a user can select when particular items should be given (morning, afternoon, evening, midnight or as needed). I need to print a summary page that displays when each item should be given. The rules I am trying to instate for my sorting order are as follows:
Items should always be displayed in chronological order, with
morning first and midnight last
Items that have multiple times to be
given, should be sorted with the least number of times to give first
(i.e. if Item #2 is to be given in the afternoon, midnight and as
needed and Item 3 should be given afternoon, evening, midnight and
as needed, then Item #2 should be listed first)
Items that are only to be given as needed should be listed last
Here is an example:
Item #1: Morning, Evening
Item #2: Afternoon, Midnight, As Needed
Item #3: Afternoon, Evening, Midnight, As Needed
Item #4: Evening
Item #5: As Needed
I am using PHP and MySQL, and here is my query so far:
$sth = $dbh->query("SELECT morning
afternoon,
evening
midnight
as_needed
FROM times
WHERE user_id = $user_id
ORDER BY as_needed,
morning DESC,
afternoon DESC,
evening DESC,
midnight DESC", PDO::FETCH_ASSOC);
Any ideas on how I can implement the above rules?
James's answer is pretty much how I would code it, but in his example, not_as_needed_times doesn't sort properly since you asked that items with least times should go first.
Edit: Ok, this behemoth will take care of everything:
$sth = $dbh->query("SELECT
(as_needed + morning + afternoon + evening + midnight) AS total_items,
IF((morning + afternoon + evening + midnight) = 0, 0, 1) AS not_as_needed_times,
morning, afternoon, evening, midnight, as_needed
FROM times
WHERE user_id = $user_id
ORDER BY not_as_needed_times DESC, morning DESC, total_items ASC, afternoon DESC, total_items ASC, evening DESC, total_items ASC, midnight DESC, total_items ASC
");
First we move not_as_needed_times to the end, then we push records that have morning = 1 to the top and order them by number of selected times, then we move records that have tuesday = 1 and so on.
If morning etc. are numeric, you could do:
SELECT (morning + afternoon + evening + midnight + as_needed) as total_items,
IF((morning + afternoon + evening + midnight) = 0, 0, 1) as not_as_needed_items,
morning, afternoon, evening, midnight, as_needed
FROM times
WHERE user_id = $user_id
ORDER BY not_as_needed_items desc, total_items asc
The descending sort of not_as_needed puts the as_needed only aet the bottom solving (3). The total_items asc sorts by # total items, solving (2). Since all the times are in one row, it's just a matter of display logic for (1).
Edit: incorporating fix for not_as_needed_items from the other poster.
The table shouldn't have a column for each timeframe if each row will only use one timeframe. You should have just one column to identify the record's timeframe. So make your table like this.
times
---------------
row_id
user_id
timeframe_id
rule
timeframes
---------------
timeframe_id
name
order
Query
SELECT * FROM times t INNER JOIN timeframes tf USING (timeframe_id) WHERE user_id = $user_id ORDER BY tf.order
Secondary Query
SELECT * FROM times t INNER JOIN timeframes tf USING (timeframe_id) WHERE user_id = $user_id AND tf.timeframe_id = '$selected_timeframe' ORDER BY tf.order
You arrange the timeframes order with a sorting number in the timeframes table. Then each row will be associated to a timeframe. Once you have done that then you can change the order of the timeframes without modifying code and without changing each row in the rules table (aka times).
I have the following query that outputs the users that received the highest number of favorites in the past week in descending order:
SELECT COUNT(faves.user_id) AS topFaves, faves.created_on, user_name
FROM users
INNER JOIN faves ON faves.user_id= users.id
WHERE DATE_SUB(CURDATE(),INTERVAL 7 DAY) <= created_on
GROUP BY id ORDER BY topFaves DESC
I would like to be able to extend this list to contain all users, not just from the past week, but still order them by the same criteria (the number of favorites they got in the past week and not by the number of faves they have in total).
I tried to include a subquery in the select but didnt have any luck with it.
Thanks in advance for any help
Maybe I'm missing something, but just delete this line:
WHERE DATE_SUB(CURDATE(),INTERVAL 7 DAY) <= created_on
And you'll have "all users" - still sorting by topFaves...
Also if you want to list everyone (not just 10 people), you'll need to delete:
LIMIT 10
I'm searching for a solution to this:
A customer can place a order with a price x at a time y. A customer can have unlimited number of orders.
I want to get the z top-customers with their ordering-amount within a time-frame (e.g.a month).
I'm stuck at the summing and the ordering / filtering to the top z.
Can you help me out? Thanks!
Given an orders table with customer_id, amount and time columns, you should be able to do something like this:
SELECT customer_id, sum(amount) AS total
FROM orders
GROUP BY customer_id
WHERE time BETWEEN start AND end
ORDER BY total DESCENDING
LIMIT 3
This is psuedo code, but I'd use something like:
select sum(order_total), client_id
from orders
where order_date between X and Y
group by client_id
order by sum(order_total)
limit 0, 10
This query has baffled me... I've searched the web work over a day now and I have tried numerous things.
I want to get the avg number of orders for every day of the week from my db. I can pull the total # with COUNT just fine. But I just can't figure out how to get the AVG of COUNT on a GROUP BY. I've tried subqueries... functions... everything... nothing works... maybe someone can throw me a bone.
Here is the query I started with below. I know AVG(COUNT(*)) won't work but I'll leave it at that because it shows what I want to do.
SELECT
AVG(COUNT(*)) AS avgorders,
SUM(total) AS ordertotal,
DAYNAME(STR_TO_DATE(order_time,'%m/%d/%Y %H:%i')) AS day
FROM data
GROUP BY day
ORDER BY DAYOFWEEK(STR_TO_DATE(order_time,'%m/%d/%Y %H:%i')) ASC
To get the average you don't need the grand totals for each day, you need multiple daily totals for each day.
Day | Count
__________________
Monday 5
Tuesday 4
Monday 6
Tuesday 3
... ...
Then you can average those numbers. I.e (5+6)/2 for Monday.
Something like this should work:
SELECT day_of_week, AVG(order_count) average_order FROM
(
SELECT DAYNAME(order_date) day_of_week,
DAYOFWEEK(order_date) day_num,
TO_DAYS(order_date) date,
count(*) order_count
FROM data
GROUP BY date
) temp
GROUP BY day_of_week
ORDER BY day_num
UPDATE: I was originally wrong. Group the inner SELECT by the actual date to get the correct daily totals. For instance, you need to get how many orders happened Monday (2/1/10) and Monday (2/8/10) separately. Then average those totals by the day of the week.
This will do, assuming that order_time is date or datetime field ( everyone would be hapier this way ;) ). Of course there is some approximation, because oldest order can be in Friday and newest in Monday, so amount of every day of week isn't equal, but creating separate variable for every day of week will be pain in the ass. Anyway I hope it will be helpful for now.
SET #total_weeks = (
SELECT
TIMESTAMPDIFF(
WEEK,
MIN(order_time),
MAX(order_time)
)
FROM data
);
SELECT
DAYNAME(order_time) AS day_of_week,
( COUNT(*) / #total_weeks ) AS avgorders,
COUNT(*) AS total_orders
FROM
data
GROUP BY
DAYOFWEEK(order_time)
I know this is old, but i was searching for a similar solution hoping to find something someone else had used. In hopes of not doing a sub query, i came up with the below and would love any feed back!
SELECT dayofweek(`timestamp`) as 'Day',count(`OrderID`)/count(DISTINCT day(`timestamp`)) as 'Average' FROM `Data` GROUP BY dayofweek(`timestamp`)
The idea is to divide the total orders on a given day of the week, by the total number of "Mondays" or whatever day it is. What this does not account for would be any days that had zero orders would not lower the average. That may or may not be desired depending on the application.
What you are asking doesn't make sense to me... AVG is an aggregate function and so is COUNT. What's wrong with the query above but just use: COUNT(*) AS avgorders?
Lets say you had 3 rows for day1, 2 rows for day2, 5 rows for day3, and 9 rows for day4... do you want to get back a single row result that tells you:
avgorders = (3 + 2 + 2 + 5 + 9) / 5 = 21 / 5 = 4.2
ordertotal = (3 + 2 + 2 + 5 + 9) = 21
I don't think you can get that in a single query, and you'd be better off doing the second round of aggregation in a server side language like PHP operating on the results of the first aggregation.