I have two tables
Table Users:
user_id Name
1 John
2 Alice
3 Tom
4 Charles
Table Events:
id event_id start_date end_date user_id
1 1 2013-03-02 2013-03-03 1
2 2 2013-03-02 2013-03-03 3
3 3 2013-03-04 2013-03-04 1
4 2 2013-03-10 2013-03-15 2
I already made the "input" part and is not possible to have two events for the same user in the same day (no overlapping).
I provide the month and the year as variables.
I would like to have a mysql query with results like this:
user_id 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 0 1 1 3 0 0 0 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2
3 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0
Thank you!
UPDATED
SELECT user_id,
COALESCE(MIN(CASE WHEN 1 BETWEEN DAY(start_date) AND DAY(end_date) THEN event_id END), 0) `1`,
COALESCE(MIN(CASE WHEN 2 BETWEEN DAY(start_date) AND DAY(end_date) THEN event_id END), 0) `2`,
COALESCE(MIN(CASE WHEN 3 BETWEEN DAY(start_date) AND DAY(end_date) THEN event_id END), 0) `3`,
COALESCE(MIN(CASE WHEN 4 BETWEEN DAY(start_date) AND DAY(end_date) THEN event_id END), 0) `4`,
COALESCE(MIN(CASE WHEN 5 BETWEEN DAY(start_date) AND DAY(end_date) THEN event_id END), 0) `5`,
COALESCE(MIN(CASE WHEN 6 BETWEEN DAY(start_date) AND DAY(end_date) THEN event_id END), 0) `6`,
COALESCE(MIN(CASE WHEN 7 BETWEEN DAY(start_date) AND DAY(end_date) THEN event_id END), 0) `7`,
COALESCE(MIN(CASE WHEN 8 BETWEEN DAY(start_date) AND DAY(end_date) THEN event_id END), 0) `8`,
COALESCE(MIN(CASE WHEN 9 BETWEEN DAY(start_date) AND DAY(end_date) THEN event_id END), 0) `9`,
COALESCE(MIN(CASE WHEN 10 BETWEEN DAY(start_date) AND DAY(end_date) THEN event_id END), 0) `10`,
COALESCE(MIN(CASE WHEN 11 BETWEEN DAY(start_date) AND DAY(end_date) THEN event_id END), 0) `11`,
COALESCE(MIN(CASE WHEN 12 BETWEEN DAY(start_date) AND DAY(end_date) THEN event_id END), 0) `12`,
COALESCE(MIN(CASE WHEN 13 BETWEEN DAY(start_date) AND DAY(end_date) THEN event_id END), 0) `13`,
COALESCE(MIN(CASE WHEN 14 BETWEEN DAY(start_date) AND DAY(end_date) THEN event_id END), 0) `14`,
COALESCE(MIN(CASE WHEN 15 BETWEEN DAY(start_date) AND DAY(end_date) THEN event_id END), 0) `15`
FROM
(
SELECT id, event_id,
CASE WHEN start_date < '2013-03-01' THEN '2013-03-01' ELSE start_date END start_date,
CASE WHEN end_date > '2013-03-31' THEN '2013-03-31' ELSE end_date END end_date,
user_id
FROM events
WHERE (start_date >= '2013-03-01' AND end_date <= '2013-03-31')
OR (start_date < '2013-03-01' AND end_date > '2013-03-31')
OR (start_date < '2013-03-01' AND end_date BETWEEN '2013-03-01' AND '2013-03-31')
OR (start_date BETWEEN '2013-03-01' AND '2013-03-31' AND end_date > '2013-03-31')
) q
GROUP BY user_id
Output:
| USER_ID | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
-----------------------------------------------------------------------------
| 1 | 0 | 1 | 1 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 2 | 2 | 2 | 2 | 2 |
| 3 | 0 | 2 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Here is SQLFiddle demo
I tryed this:
SELECT user_id,
COALESCE(MIN(CASE WHEN '2013-03-01' BETWEEN start_date AND end_date THEN event_id END), 0) `1`,
COALESCE(MIN(CASE WHEN '2013-03-02' BETWEEN start_date AND end_date THEN event_id END), 0) `2`,
COALESCE(MIN(CASE WHEN '2013-03-03' BETWEEN start_date AND end_date THEN event_id END), 0) `3`,
COALESCE(MIN(CASE WHEN '2013-03-04' BETWEEN start_date AND end_date THEN event_id END), 0) `4`,
COALESCE(MIN(CASE WHEN '2013-03-05' BETWEEN start_date AND end_date THEN event_id END), 0) `5`,
COALESCE(MIN(CASE WHEN '2013-03-06' BETWEEN start_date AND end_date THEN event_id END), 0) `6`,
COALESCE(MIN(CASE WHEN '2013-03-07' BETWEEN start_date AND end_date THEN event_id END), 0) `7`,
COALESCE(MIN(CASE WHEN '2013-03-08' BETWEEN start_date AND end_date THEN event_id END), 0) `8`,
COALESCE(MIN(CASE WHEN '2013-03-09' BETWEEN start_date AND end_date THEN event_id END), 0) `9`,
COALESCE(MIN(CASE WHEN '2013-03-10' BETWEEN start_date AND end_date THEN event_id END), 0) `10`,
COALESCE(MIN(CASE WHEN '2013-03-11' BETWEEN start_date AND end_date THEN event_id END), 0) `11`,
COALESCE(MIN(CASE WHEN '2013-03-12' BETWEEN start_date AND end_date THEN event_id END), 0) `12`,
COALESCE(MIN(CASE WHEN '2013-03-13' BETWEEN start_date AND end_date THEN event_id END), 0) `13`,
COALESCE(MIN(CASE WHEN '2013-03-14' BETWEEN start_date AND end_date THEN event_id END), 0) `14`,
COALESCE(MIN(CASE WHEN '2013-03-15' BETWEEN start_date AND end_date THEN event_id END), 0) `15`
FROM events
GROUP BY user_id
Related
I am trying to sum up table below into one line with 3Month, 6Month, 9Month, and so on but stuck with mysql error. I did lookup other similar posts and replaced GROUP BY alias with full case but still says contains nonaggregated column. Any help will be greatly appreciated.
mysql> SELECT ith.ItemCode, ith.TransactionDate, DATEDIFF(CURDATE(), ith.TransactionDate) AS Date_Diff,
-> (CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) BETWEEN 0 AND 90 THEN ith.TransactionQty ELSE 0 END) AS 0_90_Days,
-> (CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) BETWEEN 91 AND 180 THEN ith.TransactionQty ELSE 0 END) AS 91_180_Days,
-> (CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) BETWEEN 181 AND 270 THEN ith.TransactionQty ELSE 0 END) AS 181_270_Days,
-> (CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) > 270 THEN ith.TransactionQty ELSE 0 END) AS Over_270_Days
->
-> FROM im_itemtransactionhistory ith, ci_item i
-> WHERE ith.TransactionCode = 'PO'
-> AND ith.TransactionDate >= '2018-01-01'
-> AND ith.ItemCode = i.ItemCode
-> AND i.TotalQuantityOnHand > 0
-> AND ith.ItemCode = 512619
-> GROUP BY ith.ItemCode, ith.TransactionDate, ith.TransactionQty
->
-> ORDER BY ith.TransactionDate ASC;
+----------+-----------------+-----------+-----------+-------------+--------------+---------------+
| ItemCode | TransactionDate | Date_Diff | 0_90_Days | 91_180_Days | 181_270_Days | Over_270_Days |
+----------+-----------------+-----------+-----------+-------------+--------------+---------------+
| 512619 | 2018-03-19 | 220 | 0 | 0 | 1200 | 0 |
| 512619 | 2018-05-10 | 168 | 0 | 3600 | 0 | 0 |
| 512619 | 2018-05-11 | 167 | 0 | 600 | 0 | 0 |
| 512619 | 2018-06-15 | 132 | 0 | 3600 | 0 | 0 |
| 512619 | 2018-06-26 | 121 | 0 | 2400 | 0 | 0 |
| 512619 | 2018-07-23 | 94 | 0 | 2400 | 0 | 0 |
| 512619 | 2018-07-26 | 91 | 0 | 1200 | 0 | 0 |
| 512619 | 2018-09-10 | 45 | 1200 | 0 | 0 | 0 |
| 512619 | 2018-09-10 | 45 | 2400 | 0 | 0 | 0 |
| 512619 | 2018-10-16 | 9 | 1092 | 0 | 0 | 0 |
+----------+-----------------+-----------+-----------+-------------+--------------+---------------+
And this is what I've tried..
SELECT ith.ItemCode, ith.TransactionCode, i.TotalQuantityOnHand, DATEDIFF(CURDATE(), ith.TransactionDate),
(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) BETWEEN 0 AND 90 THEN ith.TransactionQty ELSE 0 END) AS 0_90_Days,
(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) BETWEEN 91 AND 180 THEN ith.TransactionQty ELSE 0 END) AS 91_180_Days,
(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) BETWEEN 181 AND 270 THEN ith.TransactionQty ELSE 0 END) AS 181_270_Days,
(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) > 270 THEN ith.TransactionQty ELSE 0 END) AS Over_270_Days,
SUM(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) BETWEEN 0 AND 90 THEN ith.TransactionQty ELSE 0 END) AS 3m_total,
SUM(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) BETWEEN 91 AND 180 THEN ith.TransactionQty ELSE 0 END) AS 6m_total,
SUM(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) BETWEEN 181 AND 270 THEN ith.TransactionQty ELSE 0 END) AS 9m_total,
SUM(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) > 270 THEN ith.TransactionQty ELSE 0 END) AS Over9m_total
FROM im_itemtransactionhistory ith, ci_item i
WHERE ith.TransactionCode = 'PO'
AND ith.TransactionDate >= '2018-01-01'
AND ith.ItemCode = i.ItemCode
AND i.TotalQuantityOnHand > 0
AND ith.ItemCode = 512619
GROUP BY ith.ItemCode,
(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) BETWEEN 0 AND 90 THEN ith.TransactionQty ELSE 0 END),
(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) BETWEEN 91 AND 180 THEN ith.TransactionQty ELSE 0 END),
(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) BETWEEN 181 AND 270 THEN ith.TransactionQty ELSE 0 END),
(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) > 270 THEN ith.TransactionQty ELSE 0 END)
ORDER BY ith.TransactionDate ASC
The error code would return
#1055 - Expression #4 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'mas90.ith.TransactionDate' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
And this is the output I am looking for..
+----------+-----------+-------------+--------------+---------------+
| ItemCode | 0_90_Days | 91_180_Days | 181_270_Days | Over_270_Days |
+----------+-----------+-------------+--------------+---------------+
| 512619 | 4692 | 13800 | 1200 | 0 |
+----------+-----------+-------------+--------------+---------------+
With help from Robert Kock I was able to solve this with query below.
SELECT ith.ItemCode, TEST1.total, TEST2.0_90_Days, TEST3.91_180_Days, TEST4.181_270_Days, TEST5.Over_270_Days
FROM im_itemtransactionhistory ith,
(SELECT ith.ItemCode, SUM(ith.TransactionQty) AS total
FROM im_itemtransactionhistory ith
WHERE ith.TransactionCode = 'PO'
AND ith.ItemCode = 512619
AND ith.TransactionDate >= '2018-01-01'
GROUP BY ith.ItemCode
) AS TEST1,
(SELECT ith.ItemCode, SUM(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) BETWEEN 0 AND 90 THEN ith.TransactionQty ELSE 0 END) AS 0_90_Days
FROM im_itemtransactionhistory ith
WHERE ith.TransactionCode = 'PO'
AND ith.ItemCode = 512619
AND ith.TransactionDate >= '2018-01-01'
GROUP BY ith.ItemCode
) AS TEST2,
(SELECT ith.ItemCode, SUM(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) BETWEEN 91 AND 180 THEN ith.TransactionQty ELSE 0 END) AS 91_180_Days
FROM im_itemtransactionhistory ith
WHERE ith.TransactionCode = 'PO'
AND ith.ItemCode = 512619
AND ith.TransactionDate >= '2018-01-01'
GROUP BY ith.ItemCode
) AS TEST3,
(SELECT ith.ItemCode, SUM(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) BETWEEN 181 AND 270 THEN ith.TransactionQty ELSE 0 END) AS 181_270_Days
FROM im_itemtransactionhistory ith
WHERE ith.TransactionCode = 'PO'
AND ith.ItemCode = 512619
AND ith.TransactionDate >= '2018-01-01'
GROUP BY ith.ItemCode
) AS TEST4,
(SELECT ith.ItemCode, SUM(CASE WHEN DATEDIFF(CURDATE(), ith.TransactionDate) > 270 THEN ith.TransactionQty ELSE 0 END) AS Over_270_Days
FROM im_itemtransactionhistory ith
WHERE ith.TransactionCode = 'PO'
AND ith.ItemCode = 512619
AND ith.TransactionDate >= '2018-01-01'
GROUP BY ith.ItemCode
) AS TEST5
WHERE ith.TransactionCode = 'PO'
AND ith.TransactionDate >= '2018-01-01'
AND ith.ItemCode = 512619
AND ith.ItemCode = TEST1.ItemCode
AND ith.ItemCode = TEST2.ItemCode
GROUP BY ith.ItemCode, TEST2.0_90_Days, TEST3.91_180_Days, TEST4.181_270_Days, TEST5.Over_270_Days
And posting the results hope this helps someone with same problems.
+----------+-------+-----------+-------------+--------------+---------------+
| ItemCode | total | 0_90_Days | 91_180_Days | 181_270_Days | Over_270_Days |
+----------+-------+-----------+-------------+--------------+---------------+
| 512619 | 19692 | 4692 | 13800 | 1200 | 0 |
+----------+-------+-----------+-------------+--------------+---------------+
I am trying to learn SQL and am wondering how to write this query for multiple dates. I tried using CASE but it is not outputting the correct totals. This query works.
I am trying to total the dailyrate for each reservation which is the effectively the daily sales.
SELECT SUM(dailyrate) AS 1June
FROM reservations
WHERE start_date < '2018-06-02' AND end_date > '2018-06-01';
This was my attempt using CASE but it does not produce the correct totals.
select dailyrate,
sum(case when start_date < '2018-06-02' AND end_date > '2018-06-01' then 1 else 0 end) as 1june,
sum(case when start_date < '2018-06-03' AND end_date > '2018-06-02' then 1 else 0 end) as 2june,
sum(case when start_date < '2018-06-04' AND end_date > '2018-06-03' then 1 else 0 end) as 3june
FROM reservations;
+------------------+------------------+----------+-
| start_date | end_date | dailyrate |
+------------------+------------------+----------+--
| 2018-06-01 05:00 | 2018-06-01 15:00 | 22 |
| 2018-05-21 05:00 | 2018-06-04 19:00 | 11.5 |
| 2018-06-01 15:00 | 2018-06-07 05:00 | 24 |
| 2018-06-03 05:00 | 2018-06-02 22:00 | 9.5 |
| 2018-05-21 12:00 | 2018-06-11 05:00 | 31 |
+------------------+------------------+----------+-
Are you looking for the COUNT of each daily_rate on each day?
If so, this may be the query you're after:
SELECT dailyrate,
COUNT(CASE WHEN start_date < '2018-06-02' AND end_date > '2018-06-01' THEN 1 ELSE 0 end) AS 1june,
COUNT(CASE WHEN start_date < '2018-06-03' AND end_date > '2018-06-02' THEN 1 ELSE 0 end) AS 2june,
COUNT(CASE WHEN start_date < '2018-06-04' AND end_date > '2018-06-03' THEN 1 ELSE 0 end) AS 3june
FROM reservations
GROUP BY dailyrate;
If you're looking for the SUM of the daily rates for each table, then this query may work for you:
SELECT dailyrate,
SUM(CASE WHEN start_date < '2018-06-02' AND end_date > '2018-06-01' THEN dailyrate ELSE 0 end) AS 1june,
SUM(CASE WHEN start_date < '2018-06-03' AND end_date > '2018-06-02' THEN dailyrate ELSE 0 end) AS 2june,
SUM(CASE WHEN start_date < '2018-06-04' AND end_date > '2018-06-03' THEN dailyrate ELSE 0 end) AS 3june
SUM reservations
GROUP BY dailyrate;
I think you were missing the GROUP BY, as both the SUM and COUNT functions are aggregate functions and need a GROUP BY to show the correct data.
I have a table with lunch effective date and its rate.
I need to display rate from its nearest lesser effective date (created_on) for each date column.
lunch_rate table:
created_on | rate
-----------+-------
2018-06-01 | 30
2018-06-04 | 60
Here's what I tried to do:
SELECT userId,
SUM(CASE WHEN date= '2018-06-01' AND lunchStatus = 1 THEN (SELECT MAX(rate) FROM lunch_rate WHERE DATE(created_on) <= date LIMIT 1) ELSE 0 END) '2018-06-01',
SUM(CASE WHEN date= '2018-06-02' AND lunchStatus = 1 THEN (SELECT MAX(rate) FROM lunch_rate WHERE DATE(created_on) <= date LIMIT 1) ELSE 0 END) '2018-06-02',
SUM(CASE WHEN date= '2018-06-03' AND lunchStatus = 1 THEN (SELECT MAX(rate) FROM lunch_rate WHERE DATE(created_on) <= date LIMIT 1) ELSE 0 END) '2018-06-03',
SUM(CASE WHEN date= '2018-06-04' AND lunchStatus = 1 THEN (SELECT MAX(rate) FROM lunch_rate WHERE DATE(created_on) <= date LIMIT 1) ELSE 0 END) '2018-06-04'
FROM
(
SELECT userId, lunchStatus, DATE(issuedDateTime) as date
FROM `lunch_status`
WHERE DATE(issuedDateTime) BETWEEN '2018-06-01' AND '2018-06-04'
) as a
GROUP BY userId;
But this query only gives maximum rate of all, without considering the nearest effective date.
Here's the outcome:
userId | 2018-06-01 | 2018-06-02 | 2018-06-03 | 2018-06-04
------------------------------------------------------------------------
131 | 60 | 60 | 0 | 60
132 | 60 | 60 | 60 | 0
133 | 0 | 0 | 0 | 60
134 | 0 | 0 | 0 | 60
Expected outcome:
userId | 2018-06-01 | 2018-06-02 | 2018-06-03 | 2018-06-04
------------------------------------------------------------------------
131 | 30 | 30 | 0 | 60
132 | 30 | 30 | 30 | 0
133 | 0 | 0 | 0 | 60
134 | 0 | 0 | 0 | 60
SUM(CASE WHEN ... THEN (SELECT MAX(rate) FROM lunch_rate WHERE DATE(created_on) <= date LIMIT 1) ELSE 0 END) ....',
How can I select lunch rate that was effective on that date?
If I understand correctly, you want the calculation in the subquery:
SELECT userId,
SUM(CASE WHEN date = '2018-06-01' AND lunchStatus = 1
THEN rate ELSE 0
END) as `2018-06-01`,
SUM(CASE WHEN date = '2018-06-02' AND lunchStatus = 1
THEN rate ELSE 0
END) as `2018-06-02`,
SUM(CASE WHEN date = '2018-06-03' AND lunchStatus = 1
THEN rate ELSE 0
END) as `2018-06-03`,
SUM(CASE WHEN date = '2018-06-04' AND lunchStatus = 1
THEN rate ELSE 0
END) as `2018-06-04`
FROM (SELECT ls.*, DATE(ls.issuedDateTime) as date
(SELECT lr.rate
FROM lunch_rate lr
WHERE DATE(lr.created_on) <= DATE(ls.issuedDateTime)
ORDER BY lr.created_on DESC
LIMIT 1
) as rate
FROM lunch_status ls
WHERE DATE(issuedDateTime) BETWEEN '2018-06-01' AND '2018-06-04'
) lr
GROUP BY lr.userId;
Note the other changes:
The subquery for lunch_rate does not use MAX(). Instead, it uses ORDER BY.
The column aliases are surrounded by backticks, not single quotes. I don't approve of the names (because they need to be escaped). But if you want them, use proper escape characters.
The tables are given reasonable aliases and column names are qualified.
You could try something like this:
SELECT lr1.rate
FROM lunch_rate lr1
WHERE lr1.created_on <= my_date
AND NOT EXISTS (SELECT *
FROM lunch_rate lr2
WHERE lr2.created_on > lr1.created_on
AND lr2.created_on <= my_date);
I had a problem. I have the data like below:
-----------------------
| last_login_dt |
-----------------------
| 2015-08-11 08:06:36 |
| 2015-06-10 22:06:43 |
| 2015-06-11 08:06:58 |
| 2015-09-11 08:06:45 |
-----------------------
So far, I managed to count this kind of data and turn into this using below statement:
SELECT DATE_FORMAT(last_login_dt,'%m/%Y') as `month`,
count(last_login_dt) as `total_visits` from public_user
WHERE DATE_FORMAT(last_login_dt,'%Y') = YEAR(CURDATE())
group by DATE_FORMAT(last_login_dt,'%m/%Y')
order by `month` asc;
----------------------------
| month | total_visits |
----------------------------
| 06/2015 | 2 |
| 08/2015 | 1 |
| 09/2015 | 1 |
----------------------------
The problem is, how to turn the result like below. Instead this table only have 4 rows of data, how to create a jan, feb, mar, apr ... row with total_visit = 0:
---------------------
| Month | Total |
---------------------
| Jan | 0 |
| Feb | 0 |
| Mar | 0 |
| Apr | 0 |
| May | 0 |
| Jun | 2 |
| Jul | 0 |
| Aug | 1 |
| Sep | 1 |
| Oct | 0 |
| Nov | 0 |
| Dis | 0 |
---------------------
I use your own query because it's working and I modified it a bit. Consider the query below:
SELECT `month`, `total_visits` FROM
(
SELECT * FROM
(
SELECT '01' AS `month_num`, 'Jan' As `month`, 0 AS `total_visits`
UNION
SELECT '02' AS `month_num`, 'Feb' AS `month`, 0 AS `total_visits`
UNION
SELECT '03' AS `month_num`, 'Mat' AS `month`, 0 AS `total_visits`
UNION
SELECT '04' AS `month_num`, 'Apr' AS `month`, 0 AS `total_visits`
UNION
SELECT '05' AS `month_num`, 'May' AS `month`, 0 AS `total_visits`
UNION
SELECT '06' AS `month_num`, 'Jun' AS `month`, 0 AS `total_visits`
UNION
SELECT '07' AS `month_num`, 'Jul' AS `month`, 0 AS `total_visits`
UNION
SELECT '08' AS `month_num`, 'Aug' AS `month`, 0 AS `total_visits`
UNION
SELECT '09' AS `month_num`, 'Sep' AS `month`, 0 AS `total_visits`
UNION
SELECT '10' AS `month_num`, 'Oct' AS `month`, 0 AS `total_visits`
UNION
SELECT '11' AS `month_num`, 'Nov' AS `month`, 0 AS `total_visits`
UNION
SELECT '12' AS `month_num`, 'Dec' AS `month`, 0 AS `total_visits`
UNION
SELECT DATE_FORMAT(last_login_dt,'%m') as `month_num`, DATE_FORMAT(last_login_dt,'%b') as `month`,
count(last_login_dt) as `total_visits` from public_user
WHERE DATE_FORMAT(last_login_dt,'%Y') = YEAR(CURDATE())
group by DATE_FORMAT(last_login_dt,'%m/%Y')
order by `total_visits` desc
) AS tmp
GROUP BY `month`
) AS total_visits
ORDER BY `month_num`;
It results in:
---------------------
| Month | Total |
---------------------
| Jan | 0 |
| Feb | 0 |
| Mar | 0 |
| Apr | 0 |
| May | 0 |
| Jun | 2 |
| Jul | 0 |
| Aug | 1 |
| Sep | 1 |
| Oct | 0 |
| Nov | 0 |
| Dis | 0 |
---------------------
I first created the table that displays the months and its total_visits (which is obviously 0). Then I unite your query to the derived table I created. I also added the month_num field for the sole purpose of sorting the data by month although it's not shown in the final result.
You're almost there. Try this %b in your date format string:
mysql> SELECT DATE_FORMAT(NOW(), '%b');
+--------------------------+
| DATE_FORMAT(NOW(), '%b') |
+--------------------------+
| Jun |
+--------------------------+
1 row in set (0.00 sec)
mysql>
The format for the month name is %b.
So I think you must change the %m to %b.
Try this sql if it works:
SELECT DATE_FORMAT(last_login_dt,'%b/%Y') as `month`,
count(last_login_dt) as `total_visits` from public_user
WHERE DATE_FORMAT(last_login_dt,'%Y') = YEAR(CURDATE())
group by DATE_FORMAT(last_login_dt,'%m/%Y')
order by `month` asc;
UPDATE AS OF 06/11/2015 11:57 AM GMT+8
We cannot display list of months in rows, but rather I used to make a derived column to display months and in total_visits on the row. I used case for the query to check if date is for the specific month.
SELECT
CASE WHEN DATE_FORMAT(last_login_dt,'%m') = '01' THEN count(last_login_dt) ELSE '0' END AS Jan,
CASE WHEN DATE_FORMAT(last_login_dt,'%m') = '02' THEN count(last_login_dt) ELSE '0' END AS Feb,
CASE WHEN DATE_FORMAT(last_login_dt,'%m') = '03' THEN count(last_login_dt) ELSE '0' END AS Mar,
CASE WHEN DATE_FORMAT(last_login_dt,'%m') = '04' THEN count(last_login_dt) ELSE '0' END AS Apr,
CASE WHEN DATE_FORMAT(last_login_dt,'%m') = '05' THEN count(last_login_dt) ELSE '0' END AS May,
CASE WHEN DATE_FORMAT(last_login_dt,'%m') = '06' THEN count(last_login_dt) ELSE '0' END AS Jun,
CASE WHEN DATE_FORMAT(last_login_dt,'%m') = '07' THEN count(last_login_dt) ELSE '0' END AS Jul,
CASE WHEN DATE_FORMAT(last_login_dt,'%m') = '08' THEN count(last_login_dt) ELSE '0' END AS Aug,
CASE WHEN DATE_FORMAT(last_login_dt,'%m') = '09' THEN count(last_login_dt) ELSE '0' END AS Sep,
CASE WHEN DATE_FORMAT(last_login_dt,'%m') = '10' THEN count(last_login_dt) ELSE '0' END AS Oct,
CASE WHEN DATE_FORMAT(last_login_dt,'%m') = '11' THEN count(last_login_dt) ELSE '0' END AS Nov,
CASE WHEN DATE_FORMAT(last_login_dt,'%m') = '12' THEN count(last_login_dt) ELSE '0' END AS `Dec`
FROM public_user;
The result will be:
------------------------------------------------------------------------
| Jan | Feb | Mar| Apr| May| Jun| Jul| Aug | Sep| Oct | Nov | Dec |
------------------------------------------------------------------------
| 0 | 0 | 0 | 0 | 0 | 2 | 0 | 1 | 1 | 0 | 0 | 0 |
------------------------------------------------------------------------
I would like to get results based on SUM from table (history), where username contains 'red' and grouped by month. here the query :
select month(date),
SUM(CASE WHEN status='success' THEN 1 ELSE 0 END) as total_sucess,
SUM(CASE WHEN status='failed' THEN 1 ELSE 0 END) as total_failed
from history
where date between '201305%' AND '201311%' AND username like '%#red%'
GROUP BY month(history.date);
the results :
+------------+--------------+--------------+
| month(date) | total_sucess | total_failed |
+------------+--------------+--------------+
| 5 | 10960 | 3573 |
| 6 | 2336 | 1202 |
| 7 | 2211 | 1830 |
| 8 | 5312 | 3125 |
| 9 | 9844 | 5407 |
| 10 | 6351 | 3972 |
+------------+--------------+--------------+
the question is , how do I get distinct total_success and total_failed SUM? just in one query ?
I've tried using this
select month(tgl),
SUM(CASE WHEN status='success' THEN 1 ELSE 0 END) as total_sucess,
SUM(DISTINCT (username) CASE WHEN status='success' THEN 1 ELSE 0 END) as distinct_total_sucess,
SUM(CASE WHEN status='failed' THEN 1 ELSE 0 END) as total_failed,
SUM(DISTINCT (username) CASE WHEN status='failed' THEN 1 ELSE 0 END) as distinct_failed_sucess
from history_auth
where tgl between '201305%' AND '201311%' AND username like '%#t.sel%'
GROUP BY month(history_auth.tgl);
but get error sql syntax... i have no idea with this :(
Best I can make out of your requirement is that you want the number of distinct usernames each month that succeeded / failed.
If so I think you need a pair of sub selects to get those figures.
Rejigged the query (adding another sub select to get the 6 months, rather than relying on all months being represented.
SELECT Sub1.aMonth,
SUM(CASE WHEN history.status='success' THEN 1 ELSE 0 END) as total_sucess,
SUM(CASE WHEN history.status='failed' THEN 1 ELSE 0 END) as total_failed,
IFNULL(SuccessCount, 0),
IFNULL(FailedCount, 0)
FROM
(
SELECT MONTH(DATE_SUB('2013-11-01', INTERVAL 0 MONTH)) AS aMonth
UNION SELECT MONTH(DATE_SUB('2013-11-01', INTERVAL 1 MONTH))
UNION SELECT MONTH(DATE_SUB('2013-11-01', INTERVAL 2 MONTH))
UNION SELECT MONTH(DATE_SUB('2013-11-01', INTERVAL 3 MONTH))
UNION SELECT MONTH(DATE_SUB('2013-11-01', INTERVAL 4 MONTH))
UNION SELECT MONTH(DATE_SUB('2013-11-01', INTERVAL 5 MONTH))
UNION SELECT MONTH(DATE_SUB('2013-11-01', INTERVAL 6 MONTH))
) Sub1
LEFT OUTER JOIN history
ON MONTH(history.date) = Sub1.aMonth
AND username LIKE '%#red%'
LEFT OUTER JOIN
(
SELECT MONTH(date) AS aMonth, COUNT(DISTINCT username) AS SuccessCount
FROM history
WHERE status='success'
AND username LIKE '%#red%'
GROUP BY MONTH(date)
) Sub2
ON Sub1.aMonth = Sub2.aMonth
LEFT OUTER JOIN
(
SELECT MONTH(date) AS aMonth, COUNT(DISTINCT username) AS FailedCount
FROM history
WHERE status='failed'
AND username LIKE '%#red%'
GROUP BY MONTH(date)
) Sub3
ON Sub1.aMonth = Sub3.aMonth
GROUP BY Sub1.aMonth, SuccessCount, FailedCount