SQL select statement fails to retrieve data falling within specified date range - mysql

I have a query that's meant to return various statistics related to items released within some time period between yesterday and the first of the month last year. For the most part, the following query works as expected.
SELECT DATE_FORMAT(A.ReleaseDate, '%Y-%m') AS FormattedReleaseDate, COUNT(*) AS ReleaseCount, SUM(A.SalesPrice)/COUNT(*) AS MAPAvg, SUM(B.TotalCost)/COUNT(*) AS COGSAvg
FROM item_info A, status B
WHERE A.ReleaseDate BETWEEN '2015-02-01' AND '2016-02-22'
AND A.ListID = B.ListID
GROUP BY MONTH(A.ReleaseDate)
ORDER BY FormattedReleaseDate DESC
This retrieves the specified statistics for every month between 2/1/15 and 2/22/16. However, it's not returning anything from this month. Just to check, I ran this exact same query, replacing the start date above with 2016-02-01, which retrieved the results I expected for just this month. Out of desperation I tried using a different column from item_info that serves the same purpose as status' TotalCost column, thereby alleviating the need for any sort of table join, but I'm still not getting the results from this month. I know it exists and falls within the date range. What exactly is wrong with my first query? I haven't specified a limit to the number of results.

First, you should:
group by FormattedReleaseDate
So if month is repeated in two different years shows as many rows as different pairs month-year are (and not stacking them together in one month, just giving you 12 rows as much).
You should try also:
WHERE STR_TO_DATE(A.ReleaseDate, '%Y-%m-%d')
between STR_TO_DATE('01/02/2015 00:00:00', '%c/%e/%Y %H:%i:%s')
and STR_TO_DATE('22/02/2016 23:59:59', '%c/%e/%Y %H:%i:%s')
just to ensure your filter is more accurate.
So the entire query would be:
SELECT DATE_FORMAT(A.ReleaseDate, '%Y-%m') AS FormattedReleaseDate, COUNT(*) AS ReleaseCount, SUM(A.SalesPrice)/COUNT(*) AS MAPAvg, SUM(B.TotalCost)/COUNT(*) AS COGSAvg
FROM item_info A, status B
WHERE
STR_TO_DATE(A.ReleaseDate, '%Y-%m-%d')
between STR_TO_DATE('01/02/2015 00:00:00', '%c/%e/%Y %H:%i:%s')
and STR_TO_DATE('22/02/2016 23:59:59', '%c/%e/%Y %H:%i:%s')
AND A.ListID = B.ListID
GROUP BY FormattedReleaseDate
ORDER BY FormattedReleaseDate DESC

I wasn't grouping the data properly.
SELECT DATE_FORMAT(A.ReleaseDate, '%Y-%m') AS FormattedReleaseDate, COUNT(*) AS ReleaseCount, SUM(A.SalesPrice)/COUNT(*) AS MAPAvg, SUM(B.TotalCost)/COUNT(*) AS COGSAvg
FROM item_info A, inventory_status B
WHERE A.ListID = B.ListID
AND A.ReleaseDate BETWEEN '$startDate' AND '$endDate'
AND A.HideInDealerPricelist = 0
GROUP BY YEAR(A.ReleaseDate), MONTH(A.ReleaseDate)
ORDER BY FormattedReleaseDate DESC

Related

Avg function not returning proper value

I expect this query to give me the avg value from daily active users up to date and grouped by month (from Oct to December). But the result is 164K aprox when it should be 128K. Why avg is not working? Avg should be SUM of values / number of current month days up to today.
SELECT sq.month_year AS 'month_year', AVG(number)
FROM
(
SELECT CONCAT(MONTHNAME(date), "-", YEAR(DATE)) AS 'month_year', count(distinct id_user) AS number
FROM table1
WHERE date between '2020-10-01' and '2020-12-31 23:59:59'
GROUP BY EXTRACT(year_month FROM date)
) sq
GROUP BY 1
Ok guys thanks for your help. The problem was that on the subquery I was pulling the info by month and not by day. So I should pull the info by day there and group by month in the outer query. This finally worked:
SELECT sq.day_month, AVG(number)
FROM (SELECT date(date) AS day_month,
count(distinct id_user) AS number
FROM table_1
WHERE date >= '2020-10-01' AND
date < '2021-01-01'
GROUP BY 1
) sq
GROUP BY EXTRACT(year_month FROM day_month)
Do not use single quotes for column aliases!
SELECT sq.month_year, AVG(number)
FROM (SELECT CONCAT(MONTHNAME(date), '-', YEAR(DATE)) AS month_year,
count(distinct id_user) AS number
FROM table1
WHERE date >= '2020-10-01' AND
date < '2021-01-01'
GROUP BY month_year
) sq
GROUP BY 1;
Note the fixes to the query:
The GROUP BY uses the same columns as the SELECT. Your query should return an error (although it works in older versions of MySQL).
The date comparisons have been simplified.
No single quotes on column aliases.
Note that the outer query is not needed. I assume it is there just to illustrate the issue you are having.

SQL: Order by date, only month and year given - Full Group on

I have an SQL database which is setted to full group on mode. My goal is to get the amount of rows (ID's) for every month. This is why I say Group By Datum. Because of the full group mode I cannot simply say Order By created_at. Because I have selected only %m.%Y. So I can only work with Datum which is cointaing my month and year.
I already tried to connect those values like CONCAT('DATE_FORMAT(created_at, '%Y-%m'), "-01 00:00:00") but also this isn't working... Even if I turn it into a UNIX Timestamp it isn't working: UNIX_TIMESTAMP(CONCAT('DATE_FORMAT(created_at, '%Y-%m'), "-01 00:00:00"))
I even tried this one:
Order By Year(DATE_FORMAT(created_at, '%Y')), Month DATE_FORMAT(created_at, '%m') But it isn't also working...
How can I sort my result by month and year without changing the Select values?
Sofar this is my actual SQL Query. Not working either.. I am nearly trying to find a solution since 1 hour...
SELECT COUNT(ID) AS Anzahl, DATE_FORMAT(created_at, '%m.%Y') AS Datum
FROM leads
WHERE created_at >= '2015-01-01' AND created_at <= '2018-01-01'
AND shopID = 4184
GROUP BY Datum
ORDER BY UNIX_TIMESTAMP(STR_TO_DATE(Datum, '%Y-%m-01 00:00:00'))
I would appreciate any kind of help! And no, I cannot change the Select values or turn off the full_group_mode.
The following will sort by year and then month in ascending order:
order by substring(datum,4,4), substring(datum,1,2)
sqlfiddle:http://sqlfiddle.com/#!9/16fab4/3
ORDER BY DATE_FORMAT(created_at, '%Y'), date_format(created_at, '%M') desc
This will sort the results by year ascending then by month descending.
Take a look at this SQL Fiddle to see the query using MySql 5.6

MySQL left join structure not returning months with 0 orders

I have two tables:
shine_orders
LU_CALENDAR
For context:
LU_CALENDAR is essentially a table containing all possible dates in a range. It has a days column called Calendar_date with all datestamps such as 2000-01-01.
shine_orders contains my orders, with a dt column that has a datetime stamp such as "2011-06-15 10:54:09".
I'm trying to return a value for all months in a range, even if for a particular app_id in shine_orders there are no rows on some months. The latter is what I'm struggling with. I can't get it to return data where the result was 0.
SQL Statement so far:
SELECT DATE_FORMAT(dt, '%b %y') as dtstr, COUNT(*)
FROM shine_orders
LEFT JOIN LU_CALENDAR
ON Date(shine_orders.dt) = LU_CALENDAR.Calendar_Date
WHERE shine_orders.type = 'PayPal'
AND shine_orders.app_id = '5'
AND DATE_ADD(LU_CALENDAR.Calendar_Date, INTERVAL 2 YEAR) > NOW()
GROUP BY dtstr
ORDER BY DATE_FORMAT(dt, '%y%m') ASC
Example output:
Would anybody here have any ideas what I'm doing wrong?
First off, you appear to have all the months in your example output. But I understand that your question is that there are some months that are skipped because the example output is zero.
I think that a right join will be appropriate instead of a left join in this case, which should mean that every row in the field calendar_date gets shown. Also, since you are right joining onto the table LU_CALENDAR, you need to make sure you group by something in LU_CALENDAR; so for your first line try:
SELECT DATE_FORMAT(Calendar_Date, '%b %y') as dtstr, COUNT(*)
This seemed to do the trick:
SELECT DATE_FORMAT(LU_CALENDAR.Calendar_Date, '%b %y') as dtstr, IFNULL(COUNT(shine_orders.id),0) as COUNT
FROM shine_orders
RIGHT JOIN LU_CALENDAR
ON LU_CALENDAR.Calendar_Date = Date(shine_orders.dt)
AND shine_orders.app_id = '5'
WHERE LU_CALENDAR.Calendar_Date
BETWEEN DATE(DATE_SUB(NOW() , INTERVAL 2 year)) AND DATE(NOW())
GROUP BY DATE_FORMAT(LU_CALENDAR.Calendar_Date, '%y%m')
ORDER BY DATE_FORMAT(LU_CALENDAR.Calendar_Date, '%y%m') ASC

Result by server Date

how to add query result as current date and less days. do not want fixed days pl help in mysql
select
Winner,
Coupon,
DATE_FORMAT(date, '%d-%m-%Y') AS `Date`
FROM table2
ORDER BY DATE_FORMAT(date, '%d-%m-%Y')
LIMIT 1, 30
You can add a where clause to that statement and use <= now() to get the rows less than or equal to the current datetime.
select
Winner,
Coupon,
DATE_FORMAT(date, '%d-%m-%Y') AS `Date`
FROM table2
where datecolumn<=now()
ORDER BY DATE_FORMAT(date, '%d-%m-%Y')
You can use limit 1 to return just one row. http://dev.mysql.com/doc/refman/5.7/en/select.html
Your current limit statement, LIMIT 1, 30, is returning the second row though the thirty first row (the first value is the offset, the second is the number of rows).

Get percentage of total when using GROUP BY in SQL query

I have a SQL query that I'm using to return the number of training sessions recorded by a client on each day of the week (during the last year).
SELECT COUNT(*) total_sessions
, DAYNAME(log_date) day_name
FROM programmes_results
WHERE log_date >= DATE_SUB(CURDATE(), INTERVAL 1 YEAR)
AND log_date <= CURDATE()
AND client_id = 7171
GROUP
BY day_name
ORDER
BY FIELD(day_name, 'MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY')
I would like to then plot a table showing these values as a percentage of the total, as opposed to as a 'count' for each day. However I'm at a bit of a loss as to how to do that without another query (which I'd like to avoid).
Any thoughts?
Use a derived table
select day_name, total_sessions, total_sessions / sum(total_sessions) * 100 percentage
from (
query from your question goes here
) temp
group by day_name, total_sessions
You can add the number of trainings per day in your client application to get the total count. This way you definitely avoid having a 2nd query to get the total.
Use the with rollup modifier in the query to get the total returned in the last row:
...GROUP BY day_name WITH ROLLUP ORDER BY ...
Use a subquery to return the overall count within each row
SELECT ..., t.total_count
...FROM programmes_results INNER JOIN (SELECT COUNT(*) as total_count FROM programmes_results WHERE <same where criteria>) as t --NO join condition
...
This will have the largest performance impact on the database, however, it enables you to have the total number in each row.