I'm trying to get the data per every month.
I'm a newbie at MySQL.
I just google and learn from the internet.
So, My Query may be not suitable.
If not suitable, please fix my query.
HERE IS MY QUERY
SELECT
SUM( cr_dt > EXTRACT( YEAR_MONTH FROM CURDATE() )
AND
cr_dt < EXTRACT( YEAR_MONTH FROM CURDATE() + INTERVAL 1 MONTH )
) as thisMonth,
SUM( cr_dt > EXTRACT( YEAR_MONTH FROM CURDATE() - INTERVAL 1 MONTH
AND
cr_dt < EXTRACT( YAER_MONTH FROM CURDATE()
) as last1Month
FROM MYTABLE
I just found the EXTRACT() and INTERVAL, but I don't know it may suitable.
If you have a better way to solve, share please.
WHAT I EXPECT
| thisMonth | last1Month |
+-----------+------------+
| 123 | 1294 |
WHAT I SEE NOW
| thisMonth | last1Month |
+-----------+------------+
| 0 | 0 |
SAMPLE DATAS
| idx | cr_dt |
+-----+---------------------+
| 1 | 2018-02-01 17:00:00 |
| 2 | 2018-02-19 16:00:00 |
| 3 | 2018-02-28 15:00:00 |
| 4 | 2018-03-04 14:00:00 |
| 5 | 2018-04-01 13:00:00 |
| 6 | 2018-04-09 12:00:00 |
| 7 | 2018-04-12 11:00:00 |
| 8 | 2018-04-17 10:00:00 |
You need to use conditional aggregation here, something like this:
SELECT
COUNT(CASE WHEN cr_dt >= DATE_FORMAT(CURRENT_DATE, '%Y/%m/01')
THEN 1 END) AS thisMonth,
COUNT(CASE WHEN cr_dt >= DATE_FORMAT(CURRENT_DATE - INTERVAL 1 MONTH, '%Y/%m/01') AND
cr_dt < DATE_FORMAT(CURRENT_DATE, '%Y/%m/01') THEN 1 END) AS last1Month
FROM MYTABLE
WHERE cr_dt >= DATE_FORMAT(CURRENT_DATE - INTERVAL 1 MONTH, '%Y/%m/01');
More typically you might see this sort of query using a GROUP BY clause, to compute aggregates over individual groups. In your case, however, it appears you want to aggregate over the entire table.
Related
I have a table of printers with a warranty start and warrant end date stored as a date field in our MYSQL database
I want to visualise the warranty end dates using the current date as a traffic lights system
Red - warranties ended
Amber - warranties ending within 90 days
Green - warranties that end in more than 90 days
Example data
+--------------------------------------+-----------------+---------------+
| id | warrantystart_c | warrantyend_c |
+--------------------------------------+-----------------+---------------+
| 001c28c4-b9cf-11e9-88a2-020683bef092 | 2018-07-13 | 2020-07-12 |
| 453b9ba2-b9ce-11e9-8fd6-0265ed7510c2 | 2018-09-26 | 2020-09-25 |
| 5c8353e2-0585-11ea-bbe5-066c2def7d44 | 2018-09-26 | 2020-09-25 |
| 71F1934 | 2018-08-28 | 2020-08-27 |
| 71F1936 | 2018-08-28 | 2020-08-27 |
| 71F2367 | 2018-09-03 | 2020-09-02 |
| 001c28c4-b9cf-11e9-88a2-020683bef092 | 2018-07-13 | 2020-07-12 |
| 0024d2ca-fb2f-11e9-8fcc-0265ed7510c2 | 2019-08-20 | 2022-08-19 |
| 00514c1c-6a5a-11e9-9026-0265ed7510c2 | 2019-04-18 | 2022-04-17 |
| 00613772-bdc4-11e9-8c8f-0265ed7510c2 | 2019-07-01 | 2022-06-30 |
| 006ac524-ef5d-11e9-b323-020683bef092 | 2019-09-30 | 2022-09-29 |
| 006b3ea2-e911-11e9-8ab6-0265ed7510c2 | 2019-10-07 | 2022-10-06 |
| 008fb146-f501-11e9-9875-06a63d65978a | 2018-02-14 | 2021-02-13 |
| 0130078c-d2ff-11e9-96e7-06a63d65978a | 2019-08-23 | 2022-08-22 |
| 0180c41e-bf5a-11e9-8abf-06a63d65978a | 2019-07-25 | 2022-07-24 |
| 0279f4ce-bdc2-11e9-ac0d-020683bef092 | 2019-07-01 | 2022-06-30 |
| 002f826c-c7cf-11e9-9104-0265ed7510c2 | NULL | 1969-12-31 |
| 031b46b4-113f-11ea-80e4-020683bef092 | 2014-07-10 | 2017-07-09 |
| 0af91f74-52da-11e9-947b-0265ed7510c2 | 2019-04-01 | 2019-04-30 |
| 0c89a096-f5bb-11e9-9313-066c2def7d44 | 1900-01-02 | 1905-01-01 |
+--------------------------------------+-----------------+---------------+
from this table the result I'm looking to get is
+-----+-------+-------+--+
| Red | amber | green | |
+-----+-------+-------+--+
| 4 | 6 | 10 | |
+-----+-------+-------+--+
I have tried three WHERE clauses to get this data
snc.warrantyend_c < current_date // Red
snc.warrantyend_c BETWEEN CURDATE() and DATE_ADD(CURDATE(), INTERVAL 90 DAY) // Amber
snc.warrantyend_c > subdate(current_date, INTERVAL 90 DAY) // Green
I just wandered if there's a better way to do the where clauses and an efficient way to do this all in one query or should I use sub queries?
You can aggregate and sum() the expressions for the different colors. This works as Boolean expressions in numeric context are interpreted as 1 for true and 0 for false in MySQL.
SELECT sum(snc.warrantyend_c < current_date) red,
sum(snc.warrantyend_c BETWEEN current_date and date_add(current_date, INTERVAL 90 DAY)) amber,
sum(snc.warrantyend_c > subdate(current_date, INTERVAL 90 DAY)) green
FROM elbat snc;
You're correct that your existing individual queries will get you the data you need:
SELECT COUNT(*) as red FROM warrantiesWHERE end < current_date;
SELECT COUNT(*) as yellow FROM warranties WHERE end BETWEEN CURDATE() and DATE_ADD(CURDATE(), INTERVAL 90 DAY);
SELECT COUNT(*) as green FROM warrantiesWHERE end > subdate(current_date, INTERVAL 90 DAY);
But these can be combined with a CASE statement as a separate column:
SELECT
*,
CASE
WHEN end < current_date THEN 'red'
WHEN end BETWEEN CURDATE() and DATE_ADD(CURDATE(), INTERVAL 90 DAY) THEN 'yellow'
WHEN end > subdate(current_date, INTERVAL 90 DAY) THEN 'green'
END as color
FROM warranties;
And then finally you can use GROUP BY on this query to get the counts:
SELECT
color,
COUNT(*) as count
FROM (
SELECT
*,
CASE
WHEN end < current_date THEN 'red'
WHEN end BETWEEN CURDATE() and DATE_ADD(CURDATE(), INTERVAL 90 DAY) THEN 'yellow'
WHEN end > subdate(current_date, INTERVAL 90 DAY) THEN 'green'
END as color
FROM warranties
) colors
GROUP BY color;
Working example at http://sqlfiddle.com/#!9/aed6cd/2
Thanks for you help and I'm working through some lessons to learn more about the points raised. I've used this to create the full statement
SELECT
color,
COUNT(*) AS count
FROM (
SELECT
sn.id,
CASE
WHEN snc.warrantyend_c < current_date THEN 'red'
WHEN snc.warrantyend_c BETWEEN CURDATE() and DATE_ADD(CURDATE(), INTERVAL 90 DAY) THEN 'amber'
WHEN snc.warrantyend_c > subdate(current_date, INTERVAL 90 DAY) THEN 'green'
END AS color
FROM
s_serialnumber sn
LEFT JOIN s_serialnumber_cstm snc ON sn.id = snc.id_c
WHERE
snc.dealer_id_c = "1000521"
) colors
GROUP BY color;
i want to get the list of date which is going to expire in a week or a month...
MySQL, and field is TIMESTAMP.
i tried below queries...
SELECT CERT_ID, date(CERTVALIDITY)
FROM mst_CERT WHERE date(CERTVALIDITY) > now() - interval 1 week ORDER BY CERTVALIDITY;
This returns all the dates from current date
SELECT date(CERTVALIDITY) from mst_CERT where curdate() =
DATE(DATE_SUB(CERTVALIDITY, INTERVAL 1 week));
returns nothing...
SELECT date(DATE_SUB(CERTVALIDITY, INTERVAL 1 MONTH)) from mst_CERT;
returns nothing...
| CT00078 | 2020-02-28 |
| CT00098 | 2020-02-29 |
| CT00011 | 2020-03-31 |
| CT00012 | 2020-03-31 |
| CT00013 | 2020-03-31 |
| CT00014 | 2020-03-31 |
| CT00075 | 2020-03-31 |
| CT00055 | 2020-03-31 |
| CT00056 | 2021-03-31 |
This will show CERT_ID's outside of a 7 day period.
SELECT CERT_ID, date(CERTVALIDITY)
FROM mst_CERT
WHERE date(CERTVALIDITY) > (NOW() + INTERVAL 7 day)
ORDER BY date(CERTVALIDITY);
This will show you valid CERT_ID's within a 7 day period.
SELECT CERT_ID, date(CERTVALIDITY)
FROM mst_CERT
WHERE date(CERTVALIDITY) BETWEEN NOW() AND (NOW() + INTERVAL 7 day)
ORDER BY date(CERTVALIDITY);
Your first query is almost right. You made a mistake of subtracting interval of 1 week but you actually had to add interval.
SELECT CERT_ID, DATE(CERTVALIDITY)
FROM ms_CERT
WHERE DATE(CERTVALIDITY) < NOW() + INTERVAL 1 WEEK AND DATE(CERTVALIDITY) > NOW()
ORDER BY CERTVALIDITY;
Above Query will return following result
| CT00078 | 2020-02-28 |
| CT00098 | 2020-02-29 |
Please how do I sum records in my MySQL table for the last 3 months but group them by month.
I want something like this:
select SUM(amount) from table where.....
group by month
I am doing the below but it is not returning any results
SELECT MONTHNAME(a.created_at) MONTH, YEAR(a.created_at) YEAR, SUM(a.credit) as credit, SUM(a.debit)
FROM telco_transactions AS a
WHERE a.telco_id = '1' and DATE(a.created_at) = DATE_ADD(NOW(), INTERVAL -3 MONTH)
GROUP BY MONTHNAME(a.created_at), YEAR(a.created_at);
select T.date_time, SUM(T.amount) from (
-> select * from TEST_TABLE where date_time >= DATE_ADD(CURDATE(), INTERVAL -3 MONTH) and date_time <= CURDATE())
-> as T GROUP BY MONTH(T.date_time);
The table test_table looks like
+------------+--------+
| date_time | amount |
+------------+--------+
| 2017-12-24 | 30 |
| 2017-09-24 | 30 |
| 2017-12-04 | 30 |
| 2017-11-24 | 30 |
| 2017-11-09 | 30 |
| 2017-10-24 | 30 |
+------------+--------+
and the output of the query looks like
+------------+---------------+
| date_time | SUM(T.amount) |
+------------+---------------+
| 2017-09-24 | 30 |
| 2017-10-24 | 30 |
| 2017-11-24 | 60 |
| 2017-12-24 | 60 |
+------------+---------------+
I would try this:
SELECT SUM(records)
FROM TABLE_NAME
WHERE Date_Column >= DATEADD(MONTH, -3, GETDATE())
GROUP BY DATEPART(MONTH, Date_Column)
I found a answer
SELECT MONTHNAME(a.created_at) as tmonth, YEAR(a.created_at) as tYear,
SUM(a.credit) as credit, SUM(a.debit)
FROM telco_transactions AS a
WHERE a.telco_id = '1' and DATE(a.created_at) BETWEEN DATE(NOW())-INTERVAL 3 MONTH AND DATE(NOW())
GROUP BY MONTHNAME(a.created_at), YEAR(a.created_at);
I have been able to select all of the months with values from this year and last if they exist. What I am trying to do is create a future date if nothing exists for it yet with a TotalAmount of 0. I could possibly fill this in using PHP however I am hoping MYSQL will have a simpler solution.
SELECT
DATE_FORMAT(STR_TO_DATE(Invoice.Date, '%m/%e/%Y'), '%m-%Y') AS Date_Month,
SUM(Invoice.Amount) AS TotalAmount
FROM Invoice
WHERE STR_TO_DATE(Invoice.Date, '%m/%e/%Y') BETWEEN DATE_SUB(DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAYOFYEAR(CURDATE()) DAY), INTERVAL 1 YEAR), INTERVAL 2 YEAR) AND NOW()
GROUP BY Date_Month
ORDER BY Date_Month
Current Output:
01-2016 | 103077
01-2017 | 104925
02-2016 | 187065
02-2017 | 32865
03-2016 | 135525
04-2016 | 106500
05-2016 | 98812
06-2016 | 111690
07-2016 | 96193
08-2016 | 123970
09-2016 | 126356
10-2016 | 147454
11-2016 | 160254
12-2016 | 98430
Expected Output:
01-2016 | 103077
01-2017 | 104925
02-2016 | 187065
02-2017 | 32865
03-2016 | 135525
03-2017 | 0
04-2016 | 106500
04-2017 | 0
05-2016 | 98812
05-2017 | 0
06-2016 | 111690
06-2017 | 0
07-2016 | 96193
07-2017 | 0
08-2016 | 123970
08-2017 | 0
09-2016 | 126356
09-2017 | 0
10-2016 | 147454
10-2017 | 0
11-2016 | 160254
11-2017 | 0
12-2016 | 98430
12-2017 | 0
You can do it with a query like this, but is not tested
SELECT
DATE_FORMAT(STR_TO_DATE(Invoice.Date, '%m/%e/%Y'), '%m-%Y') AS Date_Month,
SUM(IF(STR_TO_DATE(Invoice.Date > NOW(), 0, Invoice.Amount)) AS TotalAmount
FROM Invoice
WHERE STR_TO_DATE(Invoice.Date, '%m/%e/%Y') BETWEEN DATE_SUB(DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAYOFYEAR(CURDATE()) DAY), INTERVAL 1 YEAR), INTERVAL 2 YEAR) AND NOW()
GROUP BY Date_Month
ORDER BY Date_Month;
These are my rows in MySql database table:
+------------+----------+-------------+
| theDate | theHour | theUserCode |
+------------+----------+-------------+
| 2015-11-16 | 06:30:00 | XX2111905 |
| 2015-11-16 | 21:30:37 | XX2112111 |
| 2015-11-16 | 22:21:29 | XX2112111 |
| 2015-11-16 | 17:15:18 | XX2142122 |
| 2015-11-16 | 04:22:13 | XX2146905 |
| 2015-11-16 | 15:15:00 | XX2146905 |
| 2015-11-16 | 21:26:00 | XX2148516 |
+------------+----------+-------------+
7 rows in set
I need extract from this table the rows with theHour between 15:00:00 and 03:00:00.
I have tried this Sql query but in output I have the Empty set.
SELECT
theDate,
theHour,
theUserCode
FROM
`tblUserRegistered`
WHERE
theDate BETWEEN DATE_SUB('2015-11-16', INTERVAL 1 DAY)
AND '2015-11-16'
AND theHour BETWEEN '15:00:00'
AND '03:00:00'
ORDER BY
theUserCode,
theDate,
theHour ASC;
Please help me, thank you so much in advance.
I used the HOUR() function in my query below to handle the check by hour. This query will include records later than 3pm (15 hours), or earlier than 3am (03 hours).
SELECT theDate, theHour, theUserCode
FROM tblUserRegistered
WHERE theDate BETWEEN DATE_SUB('2015-11-16', INTERVAL 1 DAY) AND '2015-11-16'
AND (HOUR(theHour) >= 15 OR HOUR(theHour) <= 3)
ORDER BY theUserCode, theDate, theHour ASC