I want to get the total value of multiable columns hat has same value.
Ex. I want to sum all Angry reacts in month 1, 2, 3 .... etc. but I want the total of each month alone
MONTH | ANGRY | DISGUST | HAPPY |......|PEOPLE
0 | 99 | 87 | 92 | | 250
1 | 200 | 45 | 12 | | 400
.
.
.
11 |....................................|
Database Table
You seem to be looking for simple aggregation:
select
month,
sum(angry) angry,
sum(disgust) disgust,
sum(happy) happy,
...
sum(people) people
from mytable
group by month
Also, as commented by Strawberry, you should probably consider fixing your schema. Instead of having a bunch of columns, you could have just three:
date -- a legitimate datetime column
mood -- angry, disgust, ...
value -- an integer value
With this set-up in place, your would be abe to generate a report with a query like:
select year(date), month(date), mood, sum(value)
from mytable
group by year(date), month(date), mood
use groupBy
$data = DB::table('your_table_name')->select(
DB::raw('sum(angry) as sums'))
->groupBy('months')
->get();
Related
I have a 'sales' table called phpbb_sold which records each 'sale' as a row.
I am able to use a WHERE clause with the uitemid field to select one particular item in the sales records, as seen below:
SELECT uitemid, locktime, migrated_sold FROM phpbb_sold WHERE uitemid=342;
+---------+------------+---------------+
| uitemid | locktime | migrated_sold |
+---------+------------+---------------+
| 342 | 1632523854 | 1 |
| 342 | 1634239244 | 1 |
| 342 | 1634240072 | 1 |
| 342 | 1636367271 | 1 |
+---------+------------+---------------+
uitemid = number that identifies this as a sale of X item. locktime = UNIX timestamp that shows the datetime that the item was sold. migrated_sold = the quantity of the item sold. So this is nice, I have a table that keeps a record of each sale as it happens.
What I want to achieve though, is a record of the total number of sales of this item type, for each day in a 6 month period spanning back from the current date, and including each day regardless of whether a sale was made or not. So the desired output of my query would be:
SELECT (the query I want goes here) and returns the following rows...;
+------------+------------+
| caldate | sold_total |
+------------+------------+
| 2021-09-23 | 2 |
| 2021-09-24 | 0 |
| 2021-09-25 | 1 |
| 2021-09-26 | 0 |
| 2021-09-27 | 0 |
| 2021-09-28 | 1 |
+------------+------------+
Note that each day is included as a row in the results, even where the sales total for that day is 0. I read that to do this, I would be required to create a calendar table with one column and all the days I want as rows, so I went ahead and did that:
SELECT caldate FROM phpbb_calendar;
+------------+
| caldate |
+------------+
| 2021-09-23 |
| 2021-09-24 |
| 2021-09-25 |
| 2021-09-26 |
| 2021-09-27 |
| 2021-09-28 |
+------------+
Now all that remains is for me to make the query. I need to somehow return all the rows from the phpbb_calendar table, joining the data from sum() (?) of the total migrated_sold for those days where exists, and a 0 where no sales took place.
I anticipated some issues with the UNIX timestamp, but it's okay because I am able to get caldate and locktime fields to be the same format by using from_unixtime(locktime, '%Y-%m-%d'), so both dates will be in the YYYY-MM-DD format for comparison.
Please could someone help me with this. I've gotten so close every time but it seems that everyone else's request is only slightly different from mine, so existing questions and answers have not been able to satisfy my requirements.
End goal is to use a JS chart library (AnyChart) to show a line graph of the number of sales of the item over time. But to get there, I first need to provide it with the query necessary for it to display that data.
Thanks
Update
Using this query:
SELECT c.caldate, u.uitemid, sum(v.migrated_sold) as total_sales
from phpbb_calendar c cross join
(select distinct uitemid from phpbb_sold) u left join
phpbb_sold v
on c.caldate = from_unixtime(v.locktime, '%Y-%m-%d') WHERE u.uitemid = 39 and c.caldate <= curdate() GROUP BY c.caldate ORDER BY c.caldate;
Returns:
But as you can see, it's just tallying up the total number of sales ever made or something - its clearly incrementing in a way I don't understand.
I don't want it to do that - I want it to count the number of total sales on each day individually. The results should look like this:
So that what is returned is basically a 'histogram' of sales, if any occurred, including 'empty' days where there were no sales (so these empty days must still be returned as rows).
SELECT c.caldate, u.uitemid, COALESCE(SUM(v.migrated_sold), 0) AS total_sales
FROM phpbb_calendar c
CROSS JOIN (SELECT DISTINCT uitemid FROM phpbb_sold WHERE uitemid = 37) u
LEFT JOIN phpbb_sold v
ON v.locktime BETWEEN UNIX_TIMESTAMP(TIMESTAMP(c.caldate)) AND UNIX_TIMESTAMP(TIMESTAMP(c.caldate, '23:59:59'))
AND u.uitemid = v.uitemid
WHERE c.caldate BETWEEN CURDATE() - INTERVAL 6 MONTH AND CURDATE()
GROUP BY c.caldate, u.uitemid
ORDER BY c.caldate;
N.B. I have changed your join to use the unix_timestamp as it should be more efficient and it can use any existing index on locktime
check this out:
select id, d, sum(s) from (
select U.id, d, 0 s from (
select adddate(current_date(),-rows.r) d from (
select (#row_number := #row_number + 1) r
from information_schema.columns,
(SELECT #row_number := 0) AS x
limit 200
) rows
) dates,
(SELECT distinct uitemid id FROM `phpbb_sold`) U
where d > adddate(current_date(), interval -6 month)
union
select uitemid, date(from_unixtime(locktime)),sum(migrated_sold)
from `phpbb_sold`
group by uitemid, date(from_unixtime(locktime))
) sales_union
group by id, d
order by id, d;
see dbfiddle
no need for calendar table
I have a MySQL table for product orderings named TABLE1.
Date means the date purchase has been made
The table has other columns that currently have no influence.
PRODUCT_ID | DATE | other columns
3 |2018-02-01 | other values
3 |2018-02-03 | other values
3 |2018-02-07 | other values
3 |2018-02-07 | other values
3 |2018-03-02 | other values
I know that the first time the product 3 has been ordered, is 2018-02-01
SELECT DATE FROM TABLE1 WHERE PRODUCT_ID = '3' ORDER BY DATE ASC LIMIT 1
How do I select count of product orderings per day within range of 2018-02-01 and 2019-03-16 (today) so that I could get a table like that:
DATE | ORDERS_PER_DAY
2018-02-01 | 1
2018-02-02 | 0
2018-02-03 | 1
...
2018-02-07 | 2
...
2018-03-02 | 1
...
2018-03-15 | 0
2018-03-16 | 0
Thanks for help!
You can simply use GROUP BY clause to do it.
SELECT `DATE`, COUNT(`PRODUCT_ID`) AS ORDERS_PER_DAY
FROM TABLE1
WHERE `DATE` BETWEEN '2018-02-01' AND CURDATE()
GROUP BY `DATE`
This query will result in filtering the records on your required date range and then grouping it by each day where there is data.
My syntax may not be exactly correct, but could you try something like this using the GROUP BY clause.
SELECT DATE, COUNT(*) AS ORDERS_PER_DAY
FROM TABLE1
GROUP BY DATE, PRODUCT_ID
HAVING PRODUCT_ID = '3'
you can read more about this here: https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html
I'm trying to get Sale Data of every month of particular year, but I'm having a problem building a query for it.
Here is What I've tried
SELECT COUNT(`id`) AS `total_order`
FROM orders
WHERE date BETWEEN ? AND ?
GROUP BY `total_order`
HERE is How my table look like
----------------------------------------
| id | item_name | amount | time |
| 21 | item_1 | 10 | 1506675630 |
| 22 | item_2 | 30 | 1506675630 |
| 23 | item_3 | 70 | 1506675630 |
| 24 | item_4 | 100 | 1506675630 |
----------------------------------------
Now here is what i want from the query
1 - Total Sales amount made from the beginning of the year till today.
2 - Sales made Today
3 - Sales made in Last Month
4 - Sales Made in Last 3 month
5 - Sales Made in Last 6 Month
6 - Total Number of Sales made in every month of this particular year
for e.g -
January - 20
Feb -100
March - 200 & so on.
How can i achieve this complex query?
SELECT `id` AS `Order_Number`, item_name, SUM(Amount)
FROM orders
WHERE time >= '01/01/17'
GROUP BY date
That would give you your first result. Try the others and let me know what you get
This answers your first question
SELECT
DATE_FORMAT(FROM_UNIXTIME(time), '%Y-%m') as interval,
COUNT(*) AS sales_made,
SUM(amount) AS sales_amount
FROM orders
WHERE
time BETWEEN UNIX_TIMESTAMP('2017-01-01') AND UNIX_TIMESTAMP('2018-01-01')
GROUP BY 1
ORDER BY 1;
Here is what i think would work:
for the first 5 queries try something like this.
SELECT SUM(amount)
FROM orders
WHERE DATE_FORMAT(FROM_UNIXTIME(`orders.time`), '%Y-%m-%d') BETWEEN ? AND ?
And for the last one you'll need :
SELECT DATE_FORMAT(FROM_UNIXTIME(`orders.time`), '%Y-%m-%d') AS 'date', SUM(amount)
FROM orders
WHERE date between ? AND ?
GROUP BY DATE_FORMAT(date, '%Y%m')
You can try without the FROM_UNIXTIME if it doesnt work.
I have a table:
user_id | month | value
1 | firstname_1_2017 | 5
1 | secondname_1_2017 | 4
1 | firstname_2_2017 | 7
1 | secondname_2_2017 | 8
1 | firstname_3_2017 | 5
1 | secondname_3_2017 | 4
1 | firstname_4_2017 | 7
1 | secondname_4_2017 | 8
I need sum "value" for each month with a foreach.
firstname_1_2017 + secondname_1_2017 = 9
firstname_2_2017 + secondname_2_2017 = 15
I have an array for the months:
$array_months = array( '1','2','3','4','5','6','7','8','9','10','11','12' );
So I wrote (in php):
SELECT sum(value)
FROM table
WHERE user_id = $user_id
AND month LIKE '%_$array_months_2017%'
When I write a foreach, the result is the same sum of all values repeat for each month (Example: Jan 48 points, Feb 48 points, Mar 48 points...).
I'd like this result with a foreach:
You have "9" points in January
You have "15" points in February
etc...
You should think about changing your DB design to separate Month and Year from user's name.
Not a good approach, but a solution will be to extract month year from month string and group it to calculate sum for each month.
SELECT SUBSTR(month, LOCATE('_', month) + 1) AS month_year, SUM(value)
FROM users
WHERE user_id = 1
GROUP BY month_year;
Working Fiddle
You can extract the numbers from your month column values with the SUBSTRING_INDEX() function like this, giving 3_2017.
SUBSTRING_INDEX('firstname_3_2017', '_', -2)
You can then transform that to a date-ish string with CONCAT(), yielding 1_3_2017.
CONCAT('1_',SUBSTRING_INDEX('firstname_3_2017', '_', -2))
Then you can turn that into an actual DATE value with STR_TO_DATE().
STR_TO_DATE(CONCAT('1_',SUBSTRING_INDEX('firstname_3_2017', '_', -2)),'%d_%m_%Y')
Cool, now you have a datatype you can actually work with. You can now use an aggregate query to get good stuff. Leveraging Samir's fiddle: http://sqlfiddle.com/#!9/8aabd/6/0
SELECT
SUM(value) value,
user_id,
STR_TO_DATE(CONCAT('1_',SUBSTRING_INDEX(month, '_', -2)),'%d_%m_%Y') month_begin
FROM table
GROUP BY user_id, STR_TO_DATE(CONCAT('1_',SUBSTRING_INDEX(month, '_', -2)),'%d_%m_%Y')
Summary: simple transformations of your month column can give you usable information.
Pro tip: when designing your tables try not to stuff values with different meanings into single columns. Read about normalization.
Pro tip 2: use actual DATE, TIMESTAMP, or DATETIME values for storing time-based information whenever possible. Date arithmetic and date-based indexing are powerful parts of DBMS servers.
Assuming we have a table like below
id | name | userid | score | datestamp |
------------------------------------------------------------
1 | john | 1 | 44 | 2013-06-10 14:25:55
2 | mary | 2 | 59 | 2013-06-10 09:25:51
3 | john | 1 | 38 | 2013-06-10 21:25:15
4 | elvis | 3 | 19 | 2013-06-10 07:25:18
5 | john | 1 | 100 | 2013-06-14 07:25:18
I want to select the all time high-score of each user.
so for example if the player john have played ten rounds in 2013-06-10 and his score is 430 in total for that day. and in 2013-06-14 he plays 16 rounds and his scores is 1220 in total for that day. i want to display the the best score of user john, and so on for the others players. in the example above johns best score was 2013-06-14 with score 1220.
Detailed example:
If user John plays 3 rounds in 2013-06-10. First round he scores 44, second time he scores 38 and third time he scores 55. His total score for that day is 137. And on the next day 2013-06-11 he plays 5 rounds with a total score of 220. In this example his best total score so far is 220. So it should group all scores for each day to a total. And then compare this total with other days total and display the highest total of that user
Thanks in advance
This should do the trick:
SELECT userId, name, MAX(score) as highScore
FROM (
SELECT userID, name, SUM(score) as score, date(datestamp) as scoreDate
FROM TableName
GROUP BY userID, scoreDate
) dailyScores
GROUP BY userId
The inner query fetches the totals of each user's scores on each date (timestamp converted to date to remove time information), the outer query then gets the highest total score of each date for each user.
I took the liberty of basing on J W's fiddle, and I added another row to your example data so the functionality is obvious, try it out here:
http://www.sqlfiddle.com/#!2/f6bea/3
SELECT a.*
FROM Tablename a
INNER JOIN
(
SELECT userID, MAX(score) max_Score
FROM TableName
GROUP BY userID
) b ON a.userID = b.userID AND
a.score = b.max_Score
SQLFiddle Demo
For faster searching, you need to have compound index on (userid, score). Here's how to implement it:
ALTER TABLE TableName ADD INDEX (userid, score)