First of all, thank you for reading my problem. I am very thankful for the people in the community helping others learn more about coding. As this SQL and PHP is part of my hobby, I am limited by Google and fora where I can find answers to my questions. Unfortunately, I can't find a good answer for a problem encountered.
What am I trying to do?
I run a website where you can note your kilometers and liters you filled your car and see your statistics. I want to do a big search in MySQL with a query. I know how to get the results in multiple queries (3 to be exact), but I need it to be in one single query.
What does my table look look like?
For an example I am using this table to make the problem more visual, it's named 'fillings' for now.
+---------+---------+------------+--------+--------+------------+
| tank_id | user_id | kilometers | liters | car_id | date |
+---------+---------+------------+--------+--------+------------+
| 1 | 2 | 450 | 20 | 2 | 2017-11-01 |
+---------+---------+------------+--------+--------+------------+
| 2 | 1 | 500 | 30 | 1 | 2017-12-15 |
+---------+---------+------------+--------+--------+------------+
| 3 | 2 | 490 | 25 | 2 | 2017-11-05 |
+---------+---------+------------+--------+--------+------------+
| 4 | 3 | 260 | 19 | 3 | 2017-11-07 |
+---------+---------+------------+--------+--------+------------+
| 5 | 3 | 610 | 30 | 3 | 2017-12-03 |
+---------+---------+------------+--------+--------+------------+
| 6 | 3 | 100 | 4 | 3 | 2017-12-07 |
+---------+---------+------------+--------+--------+------------+
This is a basic idea of my main table where all the fill-ups are being registrated. In reality someone can have multiple cars, but for now let's asume that a user only has one car.
What are the SQL queries?
The query that I want to make should have this result:
+---------+----------------------+---------------------+
| user_id | consumption november | consumption overall |
+---------+----------------------+---------------------+
| 2 | 20,9 | 20,9 |
+---------+----------------------+---------------------+
| 1 | | 16,7 |
+---------+----------------------+---------------------+
| 3 | 13,7 | 18,3 |
+---------+----------------------+---------------------+
As you can see, the fillings of november are taking and a consumption is being calculated. Also, an overall consumption is being calculated of all fillings from a certain type of user. I know how to make this result, devided in two queries. That's:
SELECT user_id, SUM(kilometers) / SUM(liters) as consumption overall
FROM fillings
GROUP BY user_id
And also the query:
SELECT user_id, SUM(kilometers) / SUM(liters) as consumption november
FROM fillings
WHERE 'date'
BETWEEN '2017-11-01' AND '2017-11-31'
GROUP BY user_id
So right now I want to combine the queries into one, so that I can get the result that I want. Note that in the example, someone can have a null consumption in a month, because hé or she did not fill up their car in that month.
I've looked into the options of UNION and JOIN but I can't seem to find a way to make this working.
I hope everything is clear, and if not, don't hesitate to ask and I will explain in further detail.
Thanks in advance.
Since it is possible that the records are not in range within the month, a LEFT JOIN is recommended for the date specific query:
SELECT
t1.user_id, t2.consumption_november, t1.consumption_overall
FROM (
SELECT user_id, SUM(kilometers) / SUM(liters) as consumption_overall
FROM fillings
GROUP BY user_id
) t1
LEFT JOIN
(
SELECT user_id, SUM(kilometers) / SUM(liters) as consumption_november
FROM fillings
WHERE `date` BETWEEN '2017-11-01' AND '2017-11-31'
GROUP BY user_id
) t2
ON t1.user_id = t2.user_id;
http://sqlfiddle.com/#!9/3fdce84/16
Just use conditional aggregation:
SELECT user_id,
(SUM(CASE WHEN date >= '2017-11-01' AND date < '2017-12-01'
THEN kilometers ELSE 0
END) /
SUM(CASE WHEN date >= '2017-11-01' AND date < '2017-12-01'
THEN liters
END)
) as consumption_november,
SUM(kilometers) / SUM(liters) as consumption_overall
FROM fillings
GROUP BY user_id
You can try something like
SELECT t1.user_id,
t1.consumption_overall as consumption overall,
t2.consumption_november as consumption november
FROM (
SELECT user_id, SUM(kilometers) / SUM(liters) as consumption_overall
FROM fillings
GROUP BY user_id
) as t1, (
SELECT user_id, SUM(kilometers) / SUM(liters) as consumption_november
FROM fillings
WHERE 'date'
BETWEEN '2017-11-01' AND '2017-11-31'
GROUP BY user_id
) as t2
WHERE t1.user_id = t2.user_id
It will take the results of you two queries and put them in the same table.
For the extended answer (to your question in my first answer, since it's too long to leave as a comment), use :
SELECT
t1.user_id, t2.consumption_november, t3.consumption_q, t1.consumption_overall
FROM (
SELECT user_id, SUM(kilometers) / SUM(liters) as consumption_overall
FROM fillings
GROUP BY user_id
) t1
LEFT JOIN
(
SELECT user_id, SUM(kilometers) / SUM(liters) as consumption_november
FROM fillings
WHERE [date] BETWEEN '2017-11-01' AND '2017-11-31'
GROUP BY user_id
) t2
ON t1.user_id = t2.user_id
LEFT JOIN
(
SELECT user_id, SUM(kilometers) / SUM(liters) as consumption_q
FROM fillings
WHERE [date] BETWEEN '2017-08-01' AND '2017-11-31'
GROUP BY user_id
) t3
ON t1.user_id = t3.user_id;
for a subsequent left join, just remove the semicolon from the final left join and extend the pattern, and add the new field in the SELECT clause.
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
Here's what I'm trying to do. Let's say I have this table t:
key_id | id | record_date | other_cols
1 | 18 | 2011-04-03 | x
2 | 18 | 2012-05-19 | y
3 | 18 | 2012-08-09 | z
4 | 19 | 2009-06-01 | a
5 | 19 | 2011-04-03 | b
6 | 19 | 2011-10-25 | c
7 | 19 | 2012-08-09 | d
For each id, I want to select the row containing the minimum record_date. So I'd get:
key_id | id | record_date | other_cols
1 | 18 | 2011-04-03 | x
4 | 19 | 2009-06-01 | a
The only solutions I've seen to this problem assume that all record_date entries are distinct, but that is not this case in my data. Using a subquery and an inner join with two conditions would give me duplicate rows for some ids, which I don't want:
key_id | id | record_date | other_cols
1 | 18 | 2011-04-03 | x
5 | 19 | 2011-04-03 | b
4 | 19 | 2009-06-01 | a
How about something like:
SELECT mt.*
FROM MyTable mt INNER JOIN
(
SELECT id, MIN(record_date) AS MinDate
FROM MyTable
GROUP BY id
) t ON mt.id = t.id AND mt.record_date = t.MinDate
This gets the minimum date per ID, and then gets the values based on those values. The only time you would have duplicates is if there are duplicate minimum record_dates for the same ID.
I could get to your expected result just by doing this in mysql:
SELECT id, min(record_date), other_cols
FROM mytable
GROUP BY id
Does this work for you?
To get the cheapest product in each category, you use the MIN() function in a correlated subquery as follows:
SELECT categoryid,
productid,
productName,
unitprice
FROM products a WHERE unitprice = (
SELECT MIN(unitprice)
FROM products b
WHERE b.categoryid = a.categoryid)
The outer query scans all rows in the products table and returns the products that have unit prices match with the lowest price in each category returned by the correlated subquery.
I would like to add to some of the other answers here, if you don't need the first item but say the second number for example you can use rownumber in a subquery and base your result set off of that.
SELECT * FROM
(
SELECT
ROW_NUM() OVER (PARTITION BY Id ORDER BY record_date, other_cols) as rownum,
*
FROM products P
) INNER
WHERE rownum = 2
This also allows you to order off multiple columns in the subquery which may help if two record_dates have identical values. You can also partition off of multiple columns if needed by delimiting them with a comma
This does it simply:
select t2.id,t2.record_date,t2.other_cols
from (select ROW_NUMBER() over(partition by id order by record_date)as rownum,id,record_date,other_cols from MyTable)t2
where t2.rownum = 1
If record_date has no duplicates within a group:
think of it as of filtering. Simpliy get (WHERE) one (MIN(record_date)) row from the current group:
SELECT * FROM t t1 WHERE record_date = (
select MIN(record_date)
from t t2 where t2.group_id = t1.group_id)
If there could be 2+ min record_date within a group:
filter out non-min rows (see above)
then (AND) pick only one from the 2+ min record_date rows, within the given group_id. E.g. pick the one with the min unique key:
AND key_id = (select MIN(key_id)
from t t3 where t3.record_date = t1.record_date
and t3.group_id = t1.group_id)
so
key_id | group_id | record_date | other_cols
1 | 18 | 2011-04-03 | x
4 | 19 | 2009-06-01 | a
8 | 19 | 2009-06-01 | e
will select key_ids: #1 and #4
SELECT p.* FROM tbl p
INNER JOIN(
SELECT t.id, MIN(record_date) AS MinDate
FROM tbl t
GROUP BY t.id
) t ON p.id = t.id AND p.record_date = t.MinDate
GROUP BY p.id
This code eliminates duplicate record_date in case there are same ids with same record_date.
If you want duplicates, remove the last line GROUP BY p.id.
This a old question, but this can useful for someone
In my case i can't using a sub query because i have a big query and i need using min() on my result, if i use sub query the db need reexecute my big query. i'm using Mysql
select t.*
from (select m.*, #g := 0
from MyTable m --here i have a big query
order by id, record_date) t
where (1 = case when #g = 0 or #g <> id then 1 else 0 end )
and (#g := id) IS NOT NULL
Basically I ordered the result and then put a variable in order to get only the first record in each group.
The below query takes the first date for each work order (in a table of showing all status changes):
SELECT
WORKORDERNUM,
MIN(DATE)
FROM
WORKORDERS
WHERE
DATE >= to_date('2015-01-01','YYYY-MM-DD')
GROUP BY
WORKORDERNUM
select
department,
min_salary,
(select s1.last_name from staff s1 where s1.salary=s3.min_salary ) lastname
from
(select department, min (salary) min_salary from staff s2 group by s2.department) s3
Im not very familiar with using 'join' in queries. I really tried solving this by my own, but it seems to be too hard.
I got 2 Tables:
Table 'users':
+-----------------+-----------------+
| member | online |
+-----------------+-----------------+
| mahran | 1 |
| peter | 1 |
| Jen | 1 |
| Steve | 0 |
+-----------------+-----------------+
Table 'tickets'
+-----------------+----------------+----------------+
| name | category | time |
+-----------------+----------------+----------------+
| mahran | silver | 1 |
| peter | blue | 1 |
| mahran | blue | 2 |
| peter | red | 3 |
| peter | green | 2 |
| Jen | silver | 1 |
+-----------------+----------------+----------------+
The chellange:
I need each member (users.member) who's online (users.online). The next thing is to get the category for each member (user.member = tickets.name) with the highest time (probably ORDER BY time DESC LIMIT 1).
So, for example:
Peter is online. Peters highest time is 3 at the position of category=red. So I want peter to show up in the result with his category 'red'. Mahran would show up with blue. Jen would get silver. And steve would be left out because he's not online.
I hope this was clear. In general I know how the queries would look like but theres no chance for me merging them together.
What needs to be merged:
SELECT member FROM users WHERE online = 1;
|
v for each member
SELECT category FROM tickets WHERE name=users.member ORDER BY time DESC.
So, any ideas how to solve this?
Here is a fiddle with a not working query: Click
You can do this easily with a correlated subquery:
select u.member,
(select t.category
from tickets t
where t.name = u.member
order by t.time desc
limit 1
) as MostRecentCategory
from users u
where u.online = 1;
This can make use of the following indexes: users(online, member) and ticket(member, time, category).
Here is the query you're looking for:
SELECT U.member
,T.category
FROM users U
INNER JOIN tickets T ON T.name = U.member
INNER JOIN (SELECT T2.name
,MAX(T2.time) AS [maxTime]
FROM tickets T2
GROUP BY T2.name) AS M ON M.name = T.name
AND M.maxTime = T.time
WHERE U.online = 1
The use of [name] to join the two tables is not a good practice, it's much better to use keys instead. But my query is just here to help you understanding the process of jointure.
Hope this will help you.
If i understand you correctly
SELECT DISTINCT users.member, tickets.category FROM tickets JOIN users ON users.member = tickets.name WHERE users.online = 1 ORDER BY tickets.time DESC
Can you make sql fiddle?
USE DISTINCT
stackoverflow.com/questions/11704012/mysql-distinct-join
try this
SELECT DISTINCT User.member,Ticket.category FROM users AS USER
INNER JOIN tickets AS Ticket ON (User.member = Ticket.name)
WHERE User.online = 1;
Sorry, but peter seems to be RED, It's time is 3. Don't you?
Depending on table definition, is not guaranteed to have one only result for each user.
For example, if peter has time 3 in two categories, you can get one different category depending of the SQL sorting method.
To be sure, tickets.Category and tickets.time must be in a unique key (both toghether, not a unike key for each field)
Assuming that, the Query could be this.
select t2.name, t2.category
from
tickets t2
INNER JOIN (Select
u.member, max(time)
from users u, tickets t
where
u.member = t.name
and u.online = 1
group by u.member
) as usermaxtime on t2.name = usermaxtime.member;
i have three tables( runners, stages and time)
Runners table:
+--+----+
|id|name|
+--+----+
|1 |Karl|
+--+----+
|2 |Lou |
+--+----+
Stage Table:
+--+-----+-----+---+
|id|name |order|end|
+--+-----+-----+---+
|1 |start| 1 | 0 |
+--+-----+-----+---+
|2 |bike | 2 | 0 |
+--+-----+-----+---+
|3 |run | 3 | 0 |
+--+-----+-----+---+
|4 |end | 4 | 1 |
+--+-----+-----+---+
Runners data(time) Table:
+------+-----+-----+
|runner|stage|time |
+------+-----+-----+
| 1 | 1 |10:00|
+------+-----+-----+
| 1 | 2 |10:30|
+------+-----+-----+
| 1 | 3 |11:00|
+------+-----+-----+
| 2 | 1 |10:00|
+------+-----+-----+
| 2 | 2 |10:43|
+------+-----+-----+
| 2 | 3 |11:56|
+------+-----+-----+
| 1 | 4 |12:14|
+------+-----+-----+
| 2 | 4 |12:42|
+------+-----+-----+
Well ... then what I want now is to get the results as follows( order by total time ):
+------+-----+-----+-----+-----+----------+
|runner|start|bike |run | end | Total |
+------+-----+-----+-----+-----+----------+
| Karl |10:00|10:30|11:00|12:14| 01:44:00 | <--- FIRST( one hour)
+------+-----+-----+-----+-----+----------+
| Lou |10:30|10:30|11:56|12:42| 02:12:00 | <--- SECONDS( two hours )
+------+-----+-----+-----+-----+----------+
Have any idea how I can accomplish this?
Greetings!
the following should work (times are in seconds, not in HH:MM:SS)
select r.name, rd_start.time as start, rd_bike.time as bike, rd_run.time as run, rd_end.time as end, from runner as r, rd_start.time+rd_bike.time+rd_run.time+rd_end.time as total
inner join runnerdata as rd_start on r.id=rd_start.runner and rd_start.stage=1
inner join runnerdata as rd_bike on r.id=rd_bike.runner and rd_start.stage=2
inner join runnerdata as rd_run on r.id=rd_run.runner and rd_start.stage=3
inner join runnerdata as rd_end on r.id=rd_end.runner and rd_start.stage=4
order by (rd_start.time+rd_bike.time+rd_run.time+rd_end.time)
(If you post the create tables or even better use this tool: http://sqlfiddle.com/ it would make it easier for us to test our statements)
The query would look something like this but the method for calculating the total depends on the data type of the time.
select runners.name as runner, starttime.time as start, biketime.time as bike, runtime.time as run, endtime.time as end, endtime.time - starttime.time as Total
from runners
inner join time as starttime on runners.id = starttime.runner
inner join stages as startstages on starttime.stage = startstages.id and startstages.name = 'start'
inner join time as biketime on runners.id = biketime.runner
inner join stages as bikestages on biketime.stage = bikestages.id and bikestages.name = 'bike'
inner join time as runtime on runners.id = runtime.runner
inner join stages as runstages on runtime.stage = runstages.id and runstages.name = 'run'
inner join time as endtime on runners.id = endtime.runner
inner join stages as endstages on endtime.stage = endstages.id and endstages.name = 'end'
order by endtime.time - starttime.time
This requires a join and then conditional aggregation. The final column uses timediff() to subtract the two times:
select r.name,
max(case when rt.stage = 1 then rt.time end) as start,
max(case when rt.stage = 2 then rt.time end) as walk,
max(case when rt.stage = 3 then rt.time end) as bike,
max(case when rt.stage = 4 then rt.time end) as end,
timediff(max(case when rt.stage = 4 then rt.time end),
max(case when rt.stage = 1 then rt.time end)
) as TotalTime
from RunnersTime rt join
Runners r
on rt.runner = r.id
group by r.id
order by TotalTime;
Note that the column names are fixed, so the stages table is not used. Making them dynamic would make the query much more complicated.
You would probably need to do a lot of inner joining, subquerying, and comparing this time vs. that time if you want to go with that schema, and it really won't be pretty. Alternatively if your stages are fixed you could simplify to one table with each column as a stage. If the number and names of stages need to vary (for whatever reason) then I'd suggest storing a start time and end time in your runners date/time table.
If your stages are fixed then getting the result you are looking for straight out of the database will be easy. If the stages can vary (depending on your site users configuring stages for example) then you'll want to cross-tab your data in PHP or look at this SO question if you insist on doing it in the database (which I'd discourage).
I hope this is possible in MYSQL, I am scripting with PHP.
I am trying to create multiple column on SUM of values and COUNT on table1 based on each month based with individual conditions and groupings. The tables are already joined through the accountid.
I have two tables monthlyreport(table1) & planters(table2).
Desired Results is in table 1
MONTHLY REPORT (Table 1)
REPORTID|ACCOUNTID|COMPMONTH|SUMtoDATE|COUNTtoDATE|SUMcompDATE|COUNTcompDATE|
1 | 190 | JAN | 150 | 2 | 150 | 2 |
2 | 190 | FEB | 0 | 0 | 100 | 1 |
Planters (Table 2)
PlanterID | ACCOUNTID |PLANTER | SALARY | compDATE | toDATE |
1 | 190 | aaa | 100 | Jan-1-2013 | Jan-05-2013 |
2 | 190 | bbb | 50 | Jan-9-2013 | Jan-12-2013 |
3 | 190 | aaa | 100 | Feb-1-2013 | Mar-12-2013 |
4 | 190 | bbb | 0 | Mar-5-2013 | Mar-12-2013 |
A single query with inner join already works but if I run both I get nothing because I can't seem to get the logic if it is possible.
This is what I have so far from stackoverflow but getting error.
Wish someone can refactor it or make it work.
SELECT *,
(
SELECT COUNT(planters.todate), SUM(planters.todate)
FROM monthlyreport
INNER JOIN planters ON monthlyreport.accountid = planters.accountid
WHERE monthlyreport.accountid = 190 AND MONTH(monthlyreport.compmonth) = MONTH(planters.todate)
GROUP BY monthlyreport.mthreportid, month(planters.todate)
) AS count_1,
(
SELECT COUNT(planters.compdate), SUM(planters.compdate)
FROM monthlyreport
INNER JOIN planters ON monthlyreport.accountid = planters.accountid
WHERE monthlyreport.accountid = 190 AND MONTH(monthlyreport.compmonth) = MONTH(planters.compdate)
GROUP BY monthlyreport.mthreportid, month(planters.compdate)
) AS count_2
Its not very clear, but as far as I can think, what you want is to get the two results in a single query result. Try joining them on the basis of accountID from both the tables.AS:
SELECT *
from
(select accountID,COUNT(planters.todate) as count2date, SUM(planters.todate) as sum2date
-----
-----) count_1
inner join
(SELECT accountID,COUNT(planters.compdate) as countcomp, SUM(planters.compdate) as sumcomp
-----
-----) count_2
using(accountID);
Do not use "AS" before count_1 or count_2. It is better to replace * in the outer select query with more specific attributes, like count_1.count2date or like.
Hope this helps ! If anything else is what you are looking for, do let me know.
-----UPDATE-----
After looking at your file you uploaded, I came up with the following query:
SELECT count1.compmonth, IFNULL( todatecount, 0 ) , IFNULL( todatesum, 0 ) , IFNULL( compdatecount, 0 ) , IFNULL( compdatesum, 0 )
FROM count_1
LEFT JOIN count_2 ON count_1.compmonth = count_2.compmonth
UNION
SELECT count2.compmonth, IFNULL( todatecount, 0 ) , IFNULL( todatesum, 0 ) , IFNULL( compdatecount, 0 ) , IFNULL( compdatesum, 0 )
FROM count_1
RIGHT JOIN count_2 ON count_1.compmonth = count_2.compmonth
You can format the 0's as per your wish. Also, if your database platform supports the "FULL OUTER JOIN", you can use that instead of making a union of left and right joins.
You will have to replace "FROM count_1" with:
FROM (select accountID,COUNT(planters.todate) as count2date, SUM(planters.todate) as sum2date
-----
-----) count_1
Similarly for FROM count_2. I know this looks like a huge query, but all this does is joins the 2 tables on common dates, and all the other fields that don't match are specified NULL.