I have this MySQL Query here:
SELECT
COUNT(*) ReleasePerMonth,
d.name as DevGroup_REGION
FROM
release_summary r
inner join
gti_server_info g
on r.gti_server_id = g.gti_server_id
inner join
dev_group d
on d.dev_group_id = g.dev_group_id
WHERE
r.testingFinishedOn_timestamp >= '2020-05-01 00:00:00'
AND r.testingFinishedOn_timestamp <= '2020-05-31 00:00:00'
AND r.test_type != 14
GROUP BY
d.name ;
Now, I want this to run for every month. That is,
r.testingFinishedOn_timestamp >= '2019-01-01 00:00:00'
AND r.testingFinishedOn_timestamp <= '2019-01-31 00:00:00'
and
r.testingFinishedOn_timestamp >= '2019-05-02 00:00:00'
AND r.testingFinishedOn_timestamp <= '2019-02-31 00:00:00'
Till end of year. Currently, I am doing this manually. Is there any way I can do it in an automated manner?
Clarification:
I'd want 12 seperate tables for each of the 12 months.
Try the following:
SELECT
YEAR(r.testingFinishedOn_timestamp) year,
MONTH(r.testingFinishedOn_timestamp) month,
COUNT(*) ReleasePerMonth,
d.name as DevGroup_REGION
FROM
release_summary r
inner join
gti_server_info g
on r.gti_server_id = g.gti_server_id
inner join
dev_group d
on d.dev_group_id = g.dev_group_id
WHERE
r.test_type != 14
GROUP BY
YEAR(r.testingFinishedOn_timestamp),
MONTH(r.testingFinishedOn_timestamp),
d.name
ORDER BY year, month;
A possible solution is to query data for the entire year and group by MONTH(testingFinishedOn_timestamp).
I added the query below but it's not tested:
SELECT
MONTH(r.testingFinishedOn_timestamp) ReleaseMonth,
COUNT(*) ReleasePerMonth,
d.name as DevGroup_REGION
FROM
release_summary r
inner join
gti_server_info g
on r.gti_server_id = g.gti_server_id
inner join
dev_group d
on d.dev_group_id = g.dev_group_id
WHERE
r.testingFinishedOn_timestamp >= '2020-01-01 00:00:00'
AND r.testingFinishedOn_timestamp < '2021-01-01 00:00:00'
AND r.test_type != 14
GROUP BY
d.name, MONTH(r.testingFinishedOn_timestamp);
ORDER BY
MONTH(r.testingFinishedOn_timestamp), d.name
Based on the documentation available, MONTH() function returns the number of the month, for instance for January returns 1.
If you want to have the name of the month you case use MONTHNAME() function instead of Month().
You can try the below query - using last_day()
SELECT year(r.testingFinishedOn_timestamp),month(r.testingFinishedOn_timestamp),
COUNT(*) ReleasePerMonth
FROM
release_summary r
inner join
gti_server_info g
on r.gti_server_id = g.gti_server_id
inner join
dev_group d
on d.dev_group_id = g.dev_group_id
WHERE
r.testingFinishedOn_timestamp >= date_add(date_add(LAST_DAY(now()),interval 1 DAY),interval -12 MONTH)
AND r.testingFinishedOn_timestamp <= LAST_DAY(now())
AND r.test_type != 14
GROUP BY
year(r.testingFinishedOn_timestamp),month(r.testingFinishedOn_timestamp) ;
Related
Below is a query I run to extract some data in the past 24 hours.
SELECT
s.symbol,
count(cs.symbol_id) AS mentions
FROM symbols s
LEFT JOIN comments_symbols cs ON cs.symbol_id = s.id
LEFT JOIN comments c ON c.id = cs.comment_id
WHERE c.`date` > DATE_SUB(NOW(), INTERVAL 1 DAY)
GROUP BY (s.symbol)
ORDER BY mentions
DESC LIMIT 15
However, I need 24 hour intervals of data for the past 30 days in order to show a 30-day chart.
Instead of executing this query 30 times for the each day in the past 30 days, is there an approach I can take to do it with just one query execution?
It seems executing this query 30 times per page load may not be the best way to do this, no?
I hope I explained clearly, please let me know if any details are fuzzy.
Let me assume you have a list of dates. If you don't want to list them out, you can generate them:
with recursive dates as (
select curdate() - interval 30 day as dte
union all
select dte + interval 1 day
from dates
where dte < curdate()
)
Second, the LEFT JOIN seems superfluous, because you are filtering the results using LIMIT. However, I'll leave it in. Use a cross join to generate a row for each day and symbol . . . then aggregate:
SELECT s.symbol, COUNT(cs.symbol_id) AS mentions
FROM dates d CROSS JOIN
symbols s LEFT JOIN
comments_symbols cs
ON cs.symbol_id = s.id LEFT JOIN
comments c
ON c.id = cs.comment_id AND
c.date >= d.dte AND
c.date < d.date + interval 1 day
GROUP BY d.dte, s.symbol
ORDER BY d.dte, mentions DESC
Finally, to get 15 per day, let's put that into a CTE and use window functions:
WITH sm as (
SELECT d.dte, s.symbol, COUNT(cs.symbol_id) AS mentions
FROM dates d CROSS JOIN
symbols s LEFT JOIN
comments_symbols cs
ON cs.symbol_id = s.id LEFT JOIN
comments c
ON c.id = cs.comment_id AND
c.date >= d.dte AND
c.date < d.date + interval 1 day
GROUP BY d.dte, s.symbol
)
SELECT cs.*
FROM (SELECT cs.*,
ROW_NUMBER() OVER (PARTITION BY dte ORDER BY mentions DESC) as seqnum
FROM cs
) cs
WHERE seqnum <= 15;
ORDER BY dte, mentions DESC;
Here is the code. It returns table with 0 values in months where there are no data in database. Perfect!
SELECT YEAR(k.miesiace) as year,
MONTH(k.miesiace) AS month,
IFNULL(YEAR(data_zlozenia), YEAR(k.miesiace)) order_year,
IFNULL(MONTH(data_zlozenia), MONTH(k.miesiace)) order_month,
IFNULL(MONTHNAME(data_zlozenia), MONTHNAME(k.miesiace)) monthname,
IFNULL(SUM(zp.cena_netto * ilosc), 0) sum
FROM kalendarz k
LEFT OUTER JOIN zamowienia z
on MONTH(z.data_zlozenia) = MONTH(k.miesiace) AND YEAR(z.data_zlozenia) = YEAR(k.miesiace)
LEFT OUTER JOIN zamowienia_pozycje zp on z.id_ezamowienia = zp.id_ezamowienia
WHERE k.miesiace >= DATE_SUB(now(), INTERVAL 12 MONTH)
AND k.miesiace <= now()
GROUP BY MONTH(k.miesiace), YEAR(k.miesiace)
ORDER BY YEAR(k.miesiace), MONTH(k.miesiace);
But when I add to my WHERE clause this:
AND zp.id_artykulu = 9593
it ruins my code and limits output to only months where data existed instead of all 12 months. What should I change brothers?
Move your zp in a subquery.
SELECT YEAR(k.miesiace) as year,
MONTH(k.miesiace) AS month,
IFNULL(YEAR(data_zlozenia), YEAR(k.miesiace)) order_year,
IFNULL(MONTH(data_zlozenia), MONTH(k.miesiace)) order_month,
IFNULL(MONTHNAME(data_zlozenia), MONTHNAME(k.miesiace)) monthname,
IFNULL(SUM(zp.cena_netto * zp.ilosc), 0) sum
FROM kalendarz k
LEFT OUTER JOIN zamowienia z
on MONTH(z.data_zlozenia) = MONTH(k.miesiace) AND YEAR(z.data_zlozenia) = YEAR(k.miesiace)
LEFT OUTER JOIN
(select ilosc, cena_netto, id_ezamowienia from zamowienia_pozycje
where id_artykulu = 9593) zp on z.id_ezamowienia = zp.id_ezamowienia
WHERE k.miesiace >= DATE_SUB(now(), INTERVAL 12 MONTH)
AND k.miesiace <= now()
GROUP BY MONTH(k.miesiace), YEAR(k.miesiace)
ORDER BY YEAR(k.miesiace), MONTH(k.miesiace);
I am not sure to understand your exact need correctly but I think your WHERE clause you try to add is misplaced. It might work well like this :
SELECT YEAR(k.miesiace) as year,
MONTH(k.miesiace) AS month,
IFNULL(YEAR(data_zlozenia), YEAR(k.miesiace)) order_year,
IFNULL(MONTH(data_zlozenia), MONTH(k.miesiace)) order_month,
IFNULL(MONTHNAME(data_zlozenia), MONTHNAME(k.miesiace)) monthname,
IFNULL(SUM(zp.cena_netto * ilosc), 0) sum
FROM kalendarz k
LEFT OUTER JOIN zamowienia z
on (MONTH(z.data_zlozenia) = MONTH(k.miesiace) AND YEAR(z.data_zlozenia) = YEAR(k.miesiace))
LEFT OUTER JOIN zamowienia_pozycje zp on (z.id_ezamowienia = zp.id_ezamowienia AND zp.id_artykulu = 9593)
WHERE k.miesiace >= DATE_SUB(now(), INTERVAL 12 MONTH)
AND k.miesiace <= now()
GROUP BY MONTH(k.miesiace), YEAR(k.miesiace)
ORDER BY YEAR(k.miesiace), MONTH(k.miesiace);
zp is left joined so adding this where clause:
AND zp.id_artykulu = 9593
will turn the query into kind of an inner join... rows from kalendarz table will be suppressed if there is no match in the right table. Move the condition to the on clause:
LEFT OUTER JOIN zamowienia_pozycje zp on z.id_ezamowienia = zp.id_ezamowienia and zp.id_artykulu = 9593
I have so far produced the below code to try and pull the relevant data together.
However with the '+ 7' function it is producing the below issue.
Registration date = '2018-01-01'
It is pulling back purchase dates of 2018-04-08, i.e as long as the day of the day is 7 days greater then it is being deemed acceptable. When in reality what I ma looking for is any all purchases within 7 days of the registration date.
Any advice/help would be greatly appreciated.
select *
from purchases b
inner join registrations r
on r.customer_id = b.customer_id
and day(b.purchase_date) between d(r.account_opening_date) and day(r.account_opening_date) + 7
and r.account_opening_date >= '2018-01-01 00:00:00.0'
Use DATE_ADD instead, DAY() will not work well when dates to compare are in different months.
AND b.purchase_date >= r.account_opening_date AND
b.purchase_date <= DATE_ADD(r.account_opening_date INTERVAL 7 Day)
you can use window function
select *
partition by (order by account_opening_date rows 6 preceding)
from purchases p, registrations r
where p.customer_id = r.customer_id
and r.account_opening_date >= '2018-01-01 00:00:00.0'
You can simply use +:
select *
from purchases b inner join
registrations r
on r.customer_id = b.customer_id and
b.purchase_date >= r.account_opening_date and
b.purchase_date < r.account_opening_date + interval 7 day
where r.account_opening_date >= '2018-01-01';
If you want to do this without the time component, then use the date() function:
on r.customer_id = b.customer_id and
b.purchase_date >= r.account_opening_date and
b.purchase_date <= date(r.account_opening_date) + interval 7 day
where r.account_opening_date >= '2018-01-01'
Whether you use < or <= depends on the exactly interpretation of "within 7 days". This version assumes that you really want 7-8 days.
It sounds like you need to use DATE_ADD and DATE MySQL functions.
select *
from purchases b
inner join registrations r
on r.customer_id = b.customer_id
and date(b.purchase_date) between date(r.account_opening_date) and date_add(r.account_opening_date interval 7 day)
and r.account_opening_date >= '2018-01-01 00:00:00.0'
This question already has answers here:
What is the most straightforward way to pad empty dates in sql results (on either mysql or perl end)?
(9 answers)
Closed 5 years ago.
I want to select company id, date and number from table, but this query does not show the month some companies with 0 number.
Here is the query:
SELECT c.name, date_format(e.created, '%y_%m') AS date, count(*)
FROM company c
JOIN edited e
on c.id=e.company_id AND e.created >='2016-12-13 00:00:00' AND e.created <='2017-05-20 00:00:00'
GROUP BY c.id, date
Some of results like this 4 16_12 2
4 17_01 4
4 17_04 2
4 17_05 2
without 17_03 (march). how can it show 17_03 with 0 ?
If your join not match values according to its in ON clause, not will return tuples and consequently you won't count rows. If you have a fixed set of companies and dates, you can set manually your values with UNION statement:
(SELECT 'company_name1', 'date1', COUNT(*)
FROM company c
JOIN edited e
on c.id=e.company_id AND e.created >='2016-12-13 00:00:00' AND e.created <='2017-05-20 00:00:00')
UNION
(SELECT 'company_name2', 'date2', COUNT(*)
FROM company c
JOIN edited e
on c.id=e.company_id AND e.created >='2016-12-13 00:00:00' AND e.created <='2017-05-20 00:00:00')
#and make this for companies that not will return zero at count
UNION
(SELECT c.name, date_format(e.created, '%y_%m') AS date, count(*)
FROM company c
JOIN edited e
on c.id=e.company_id AND e.created >='2016-12-13 00:00:00' AND e.created <='2017-05-20 00:00:00'
GROUP BY c.id, date)
SELECT c.id
, ym.y
, ym.m
, count(e.created) cnt
FROM ( SELECT #startDate := date_add(#startDate, interval 1 month) date
, year(#startDate) y
, month(#startDate) m
FROM HugeTable
JOIN ( SELECT #startDate := '2016-11-01'
, #endDate := '2017-05-01'
) months
WHERE #startDate < #endDate
) ym
LEFT JOIN edited e
ON year(e.created) = ym.y
AND month(e.created) = ym.m
LEFT JOIN company c
ON c.id = e.company_id
GROUP BY ym.y
, ym.m
, c.id
HugeTable can be any table with enough number of records as number of months to be displayed.
I have the following query
SELECT * FROM ".TBL_FOOT_GAMES." ORDER BY id DESC LIMIT 1
I need to add a WHERE clause on the field date_confirmed.
date_confirmed is a DATETIME type.
I need to select only rows that are within 7 days of the current moment.
MORE CODE
SELECT g.home_user, g.away_user, g.home_score, g.away_score, g.id AS gameid, g.date_confirmed,
hu.username AS home_username, au.username AS away_username, ht.team AS home_team, at.team AS away_team
FROM tbl_foot_games g INNER JOIN tbl_users hu ON hu.id = g.home_user INNER JOIN tbl_users au ON au.id = g.away_user
INNER JOIN tbl_foot_teams ht ON ht.id = g.home_team INNER JOIN tbl_foot_teams at ON at.id = g.away_team
WHERE (g.type = '1' OR g.type = '2' OR g.type = '3' OR g.type = '4') AND g.status = '3' AND g.date_confirmed BETWEEN NOW() AND DATE_SUB(NOW(), INTERVAL 50 WEEK)
ORDER BY g.id DESC LIMIT 1
The statement works fine until I add the WHERE clause for the 50 week interval.
Presuming only seven days in the future (it looks like you're going to list upcoming football games):
SELECT *
FROM `tbl`
WHERE `date_confirmed` BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 1 WEEK)
ORDER BY `id` DESC
LIMIT 1
Please read the documentation first next time; the answers are all there.
... WHERE date_confirmed BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 7 DAY) ...
Have a look at the NOW() and DATE_SUB() functions.
These should let you create a date 7 days ago, then in your where clause you can check that the datetime column is greater than this.
You can use the date_sub function of MySQL to see if the diff is 7 days or less.
SELECT * FROM ".TBL_FOOT_GAMES."
WHERE DATE_ADD(DATE_CONFIRMED, INTERVAL '7 00:00:00' DAYS_SECOND) >= TIMESTAMP(CURDATE())
ORDER BY id DESC LIMIT 1
If you are interested in seeing only 7 days of difference from current date (ignoring the time value), then you can use DATEDIFF function like this:
SELECT * FROM ".TBL_FOOT_GAMES."
WHERE DATEDIFF(CURDATE(), DATE_CONFIRMED) <= 7
ORDER BY id DESC LIMIT 1