get amount between range [closed] - mysql

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Improve this question
This a simple my table
+-----------+----------------+-----------+
| id | date | meter |
------------+----------------+-----------+
| 1 | 2103-11-01 | 5 |
| 2 | 2103-11-10 | 8 |
| 4 | 2103-11-14 | 10 |
| 6 | 2103-11-20 | 18 |
| 7 | 2103-11-25 | 25 |
| 10 | 2103-11-29 | 30 |
+-----------+----------------+-----------+
how do I get the results to the use of meters between two ranges of the results of recording time,
like bellow
+----------------+----------------+-------+-----+--------+
| date1 | date2 | start | end | amount |
+----------------+----------------+-------+-----+--------+
| 2013-11-01 | 2013-11-10 | 5 | 8 | 3 |
| 2013-11-10 | 2013-11-14 | 8 | 10 | 2 |
| 2013-11-14 | 2013-11-20 | 10 | 18 | 8 |
| 2013-11-20 | 2013-11-25 | 18 | 25 | 7 |
| 2013-11-25 | 2013-11-29 | 25 | 30 | 5 |
+----------------+----------------+-------+-----+--------+

Edit:
I got it:
select meters1.date as date1, min(meters2.date) as date2, meters1.meter as start,
meters2.meter as end, (meters2.meter - meters1.meter) as amount
from meters meters1, meters meters2 where meters1.date < meters2.date
group by date1;
Outputs:
+------------+------------+-------+-----+--------+
| date1 | date2 | start | end | amount |
+------------+------------+-------+-----+--------+
| 2013-11-01 | 2013-11-10 | 5 | 8 | 3 |
| 2013-11-10 | 2013-11-14 | 8 | 10 | 2 |
| 2013-11-14 | 2013-11-20 | 10 | 18 | 8 |
| 2013-11-20 | 2013-11-25 | 18 | 25 | 7 |
| 2013-11-25 | 2013-11-29 | 25 | 30 | 5 |
+------------+------------+-------+-----+--------+
Original Post:
This is most of the way there:
select meters1.date as date1, meters2.date as date2, meters1.meter as start,
meters2.meter as end, (meters2.meter - meters1.meter) as amount
from meters meters1, meters meters2 having date1 < date2 order by date1;
It outputs:
+------------+------------+-------+-----+--------+
| date1 | date2 | start | end | amount |
+------------+------------+-------+-----+--------+
| 2013-11-01 | 2013-11-10 | 5 | 8 | 3 |
| 2013-11-01 | 2013-11-20 | 5 | 18 | 13 |
| 2013-11-01 | 2013-11-29 | 5 | 30 | 25 |
| 2013-11-01 | 2013-11-14 | 5 | 10 | 5 |
| 2013-11-01 | 2013-11-25 | 5 | 25 | 20 |
| 2013-11-10 | 2013-11-20 | 8 | 18 | 10 |
| 2013-11-10 | 2013-11-29 | 8 | 30 | 22 |
| 2013-11-10 | 2013-11-14 | 8 | 10 | 2 |
| 2013-11-10 | 2013-11-25 | 8 | 25 | 17 |
| 2013-11-14 | 2013-11-25 | 10 | 25 | 15 |
| 2013-11-14 | 2013-11-20 | 10 | 18 | 8 |
| 2013-11-14 | 2013-11-29 | 10 | 30 | 20 |
| 2013-11-20 | 2013-11-25 | 18 | 25 | 7 |
| 2013-11-20 | 2013-11-29 | 18 | 30 | 12 |
| 2013-11-25 | 2013-11-29 | 25 | 30 | 5 |
+------------+------------+-------+-----+--------+

If it's SQL server try it this way
WITH cte AS
(
SELECT *, ROW_NUMBER() OVER (ORDER BY date) rnum
FROM table1
)
SELECT c.date date1, p.date date2, c.meter [start], p.meter [end], p.meter - c.meter amount
FROM cte c JOIN cte p
ON c.rnum = p.rnum - 1
Here is SQLFiddle demo
If it's MySQL then you can do
SELECT date1, date2, meter1, meter2, meter2 - meter1 amount
FROM
(
SELECT #d date2, date date1, #m meter2, meter meter1, #d := date, #m := meter
FROM table1 CROSS JOIN (SELECT #d := NULL, #m := NULL) i
ORDER BY date DESC
) q
WHERE date2 IS NOT NULL
ORDER BY date1
Here is SQLFiddle demo
Output in both cases:
| DATE1 | DATE2 | START | END | AMOUNT |
|------------|------------|-------|-----|--------|
| 2103-11-01 | 2103-11-10 | 5 | 8 | 3 |
| 2103-11-10 | 2103-11-14 | 8 | 10 | 2 |
| 2103-11-14 | 2103-11-20 | 10 | 18 | 8 |
| 2103-11-20 | 2103-11-25 | 18 | 25 | 7 |
| 2103-11-25 | 2103-11-29 | 25 | 30 | 5 |

MySql
SELECT DATES.date1,
DATES.date2,
m1.meter as start,
m2.meter as end,
m2.meter - m1.meter as amount
FROM
(SELECT date as date1,
(SELECT min(date)
FROM tableName t2
WHERE t2.date > t1.date) as date2
FROM tableName t1
)DATES,
tableName m1,
tableName m2
WHERE DATES.date2 IS NOT NULL
AND m1.date = DATES.date1
AND m2.date = DATES.date2
ORDER BY DATES.date1
sqlFiddle here
in MS-SQL SERVER 2002 change the word end to "end" as it complains about syntax near end

You haven't made it clear whether you're really using mySQL or SQL Server but I'm posting a solution that works for SQL 2008 and above. Might work for 2005 but I can't test that.
-- Set up a temp table with sample data
DECLARE #testData AS TABLE(
id int,
dt date,
meter int)
INSERT #testData(id, dt, meter) VALUES
(1, '2013-11-01', 5)
,(2, '2013-11-10', 8)
,(4, '2013-11-14', 10)
,(6, '2013-11-20', 18)
,(7, '2013-11-25', 25)
,(10, '2013-11-29',30)
---------------------------------------------
-- Begin SQL Server solution
;WITH cte AS (
SELECT
ROW_NUMBER() OVER (ORDER BY id) AS rownum
,id
,dt
,meter
FROM
#testData AS [date2]
)
SELECT
t1.id
,t1.dt AS [date1]
,t2.dt AS [date2]
,t1.meter AS [start]
,t2.meter AS [end]
,t2.meter - t1.meter AS [amount]
FROM
cte t1
LEFT OUTER JOIN cte t2 ON (t2.rownum = t1.rownum + 1)
WHERE
t2.dt IS NOT NULL

If you're using MySQL, then a self-join will work well here. Join the table to itself, using an ON clause to make sure you don't join the same record to itself. This will give you ((N * N) - N) permutations of your data, where N is the number of original rows.
SELECT
...
FROM
tableName first
JOIN
tableName second
ON first.id != second.id
Then, it's all about SELECTing the right stuff (including the calculation of the difference between the two meter values). To get the columns in the result set you posted, you'd probably want to SELECT:
first.date AS date1,
second.date AS date2,
first.meter AS start,
second.meter AS end,
ABS(first.meter - second.meter) AS amount
Edit
Ah, I see. I'd envisioned something like a inter-city mileage chart that you used to see on road maps (where you'd have the same cities in the rows and columns, and the cell in the intersection would indicate the number of miles between those two cities.
But it looks like you just want to compare values from one date to the next. If that's the case, you can take advantage of the way MySQL handles GROUPing and ORDERing... but be careful, because I'm not sure this is guaranteed:
mysql> SELECT
table1.date AS date1,
table2.date AS date2,
table1.meter AS start,
table2.meter AS end,
ABS(table1.meter - table2.meter) AS amount
FROM tableName table1
JOIN tableName table2
WHERE table2.date > table1.date
GROUP BY table1.date
ORDER BY table2.date - table1.date;
+---------------------+---------------------+-------+------+--------+
| date1 | date2 | start | end | amount |
+---------------------+---------------------+-------+------+--------+
| 2103-11-25 00:00:00 | 2103-11-29 00:00:00 | 25 | 30 | 5 |
| 2103-11-10 00:00:00 | 2103-11-14 00:00:00 | 8 | 10 | 2 |
| 2103-11-20 00:00:00 | 2103-11-25 00:00:00 | 18 | 25 | 7 |
| 2103-11-14 00:00:00 | 2103-11-20 00:00:00 | 10 | 18 | 8 |
| 2103-11-01 00:00:00 | 2103-11-10 00:00:00 | 5 | 8 | 3 |
+---------------------+---------------------+-------+------+--------+
5 rows in set (0.00 sec)

Related

Select complete record with earliest timestamp on a day for each employee [duplicate]

This question already has answers here:
Group by minimum value in one field while selecting distinct rows
(10 answers)
Closed 2 years ago.
I have a table that stores facial login data of employees based upon employee id. I need to get the earliest login for each employee on a day and all other logins to be ignored. I know how to get latest or earliest record for each employee but I am unable to figure out how to get earliest entry in each day by each employee.
+----+-----------+--------------------------------------+-------------+-----------------------+
| id | camera_id | image_name | employee_id | created_at |
+----+-----------+--------------------------------------+-------------+-----------------------+
| 10 | 2 | pjcc7vf142pec6li7k8kqxuqvnmhm0tyo8ib | 16 | 2020-07-11 10:40:20 |
| 11 | 2 | 9iizfdtk3m81a745ut7tzqzqh8kf9ipz2u02 | 2 | 2020-07-11 10:40:22 |
| 14 | 2 | 3p74yrq35nfaazwdo8auguvn2h5hpugtfvvw | 2 | 2020-07-11 12:07:24 |
| 15 | 2 | hpa2am40ufke7o7q2y733hh83h7ykxxdgkof | 16 | 2020-07-11 12:09:35 |
| 16 | 2 | g7adgyzloab2t4z7xx2id0a9cjqx8ojfni99 | 2 | 2020-07-11 12:09:41 |
| 17 | 2 | tapufkiuj5toxfdoikjicbe3k7tl32yj5khp | 16 | 2020-07-12 12:09:47 |
| 18 | 2 | pjcc7vf142pec6li7k8kqxuqvnmhm0tyo8ib | 16 | 2020-07-12 14:40:20 |
| 19 | 2 | 9iizfdtk3m81a745ut7tzqzqh8kf9ipz2u02 | 2 | 2020-07-12 15:40:22 |
| 20 | 2 | 3p74yrq35nfaazwdo8auguvn2h5hpugtfvvw | 2 | 2020-07-12 16:07:24 |
| 21 | 2 | hpa2am40ufke7o7q2y733hh83h7ykxxdgkof | 16 | 2020-07-12 17:09:35 |
| 22 | 2 | g7adgyzloab2t4z7xx2id0a9cjqx8ojfni99 | 2 | 2020-07-13 12:09:41 |
+----+-----------+--------------------------------------+-------------+-----------------------+
The result will look like below...
+----+-----------+--------------------------------------+-------------+-----------------------+
| id | camera_id | image_name | employee_id | created_at |
+----+-----------+--------------------------------------+-------------+-----------------------+
| 10 | 2 | pjcc7vf142pec6li7k8kqxuqvnmhm0tyo8ib | 16 | 2020-07-11 10:40:20 |
| 11 | 2 | 9iizfdtk3m81a745ut7tzqzqh8kf9ipz2u02 | 2 | 2020-07-11 10:40:22 |
| 17 | 2 | tapufkiuj5toxfdoikjicbe3k7tl32yj5khp | 16 | 2020-07-12 12:09:47 |
| 19 | 2 | 9iizfdtk3m81a745ut7tzqzqh8kf9ipz2u02 | 2 | 2020-07-12 15:40:22 |
| 22 | 2 | g7adgyzloab2t4z7xx2id0a9cjqx8ojfni99 | 2 | 2020-07-13 12:09:41 |
+----+-----------+--------------------------------------+-------------+-----------------------+
You can do:
select *
from t
where (employee_id, created_at) in (
select employee_id, min(created_at)
from t
group by employee_id, date(created_at)
)
how to get earliest entry in each day by each employee
You can filter with a correlated subquery:
select t.*
from mytable t
where t.created_at = (
select min(t1.created_at)
from mytable t1
where
t1.employee_id = t.employee_id
and t1.created_at >= date(t.created_at)
and t1.created_at < date(t.created_at) + interval 1 day
)
This query would take advantage of an index on (employee_id, created_at).
Or, if you are running MySQL 8.0, you can use window functions:
select *
from (
select
t.*,
row_number() over(
partition by employee_id, date(created_at)
order by created_at
) rn
from mytable t
) t
where rn = 1

MySQL: Getting the most counted same-value entry (statistical mode) per hour within a datetime range

I have a table like this:
+--------+---------+----------------------+--------------+----------+
| idadata | value_r | date_r | idparameter | idnode |
+--------+-----------+-----------------------+--------------+--------+
| 54620 | 66.6627 | 2014-10-16 12:01:09 | 46 | 9 |
| 54621 | 19.4953 |2014-10-16 12:01:09 | 40 | 9 |
| 54622 | 19.9384 |2014-10-16 12:01:09 | 47 | 9 |
| 54623 | 163.849 | 2014-10-16 12:01:09 | 43 | 9 |
| 54624 | 67.9257 | 2014-10-16 12:02:09 | 44 | 9 |
| 54625 | 315 | 2014-10-16 12:02:09 | 42 | 9 |
| 54626 | 0.699 | 2014-10-16 12:02:09 | 41 | 9 |
| 54627 | 67.9257 | 2014-10-16 12:03:09 | 46 | 9 |
| 54628 | 19.2308 | 2014-10-16 12:03:09 | 40 | 9 |
| 54629 | 11.207 | 2014-10-16 12:03:09 | 47 | 9 |
| 54630 | 118.743 | 2014-10-16 12:03:09 | 43 | 9 |
| 54631 | 292.5 | 2014-10-16 12:03:09 | 42 | 9 |
+---------+----------+----------------------+---------------+-------+
I need to get the statistical mode or the value_r that repeats the most for a given idparameter and idnode in a given datime interval each hour. I have managed to get the mode when I set the datetime difference for 1 hour manually. However, when I try to group by hour or time difference it doesn't work and I end up with mode of the whole Start-End datetime and not group by hours.
So far this is my code:
select value_r , date_r , max(counter_v) from
(SELECT iddata, value_r,date_r ,count( value_r ) counter_v
FROM wsnca.data dat
where dat.idnode=9 and dat.idparameter=42 and
( dat.date_r between ('2014-10-16 12:00:00') and ('2014-10-16 13:00:00') )
group by value_r
order by counter_v DESC) T;
Result:
+----------+----------------------+---------------+
| value_r | date_r | max(counter_v)|
+-----------+----------------------+--------------+
| 270 | 2014-10-16 12:03:09 | 7 |
+-----------+-----------------------+--------------+
However, the result I'm looking for would be like this:
+----------+----------------------+---------------+
| value_r | date_r | max(counter_v)|
+-----------+----------------------+--------------+
| 270 | 2014-10-16 12:00:00 | 7 |
+-----------+-----------------------+--------------+
| 90 | 2014-10-16 13:00:00 | 4 |
+-----------+-----------------------+--------------+
| 45 | 2014-10-16 14:00:00 | 9 |
+-----------+-----------------------+--------------+
| 180 | 2014-10-16 15:00:00 | 8 |
+-----------+-----------------------+--------------+
As I said before, I don't know how to group that by one hour time interval and reading from the query round at the hour datetime as in the desired table.
I know I could do it in the PHP doing several queries but would prefer to do it in the one query.
You can number the count for each value_r per hour starting with #1 for the highest count, #2 for the 2nd highest and so on and then only keep #1 rows, which will be the modes for each hour.
select date_hour, value_r, cnt from (
select * ,
#rowNum := IF(date_hour = #prevDateHour,#rowNum+1,1) rowNum,
#prevDateHour := date_hour
from (
select value_r, hour(date_r) date_hour, count(*) cnt
from wsnca.data dat
where dat.idnode=9 and dat.idparameter=42
group by value_r, hour(date_r)
) t1 order by date_hour, cnt desc
) t1 where rowNum = 1
change group by value_r into group by value_r, date_r I think that should make it
EDIT Better Response for what you want to achieve
select value_r , DATE_FORMAT(date_r, '%Y-%m-%d %H') as formatted_date, max(counter_v) from
(SELECT iddata, value_r,date_r ,count( value_r ) counter_v
FROM wsnca.data dat
where dat.idnode=9 and dat.idparameter=42 and
( dat.date_r between ('2014-10-16 12:00:00') and ('2014-10-16 13:00:00') )
group by value_r, formatted_date
order by counter_v DESC) T

mysql: Intergrate values of a table alog time

I want to integrate the v values with timediffs of t from one row to the next, in a table like this: "p_values"=
+------------+-------+----------+
| measure_id | v | t |
+------------+-------+----------+
| 1 | 32 | 10:45:00 |
| 2 | 17 | 10:42:00 |
| 3 | 20 | 10:39:00 |
| 4 | 21 | 10:36:00 |
| 5 | 35 | 10:33:00 |
| 6 | 59 | 10:30:00 |
| 7 | 47 | 10:27:00 |
| 8 | 45 | 10:24:00 |
| 9 | 40 | 10:21:00 |
| 10 | 39 | 10:18:00 |
| 11 | 42 | 10:15:00 |
+------------+-------+----------+
I want to integrate the v values with timediffs of t:
result = v[1]*(t[1]-t[2]) + v[2]*(t[2]-t[3]) + v[3]*(t[3]-t[4]) + ...
Can I do this on a single query?
I'm trying creating a table joining each column with the column below, like this:
select * from
(select measure_id, v, t from p_values order by t desc) a,
(select measure_id, v, t from p_values order by t desc) b
where a.t < b.t group by b.t desc;
+------------+----+----------+------------+----+----------+
| measure_id | v | t | measure_id | v | t |
+------------+----+----------+------------+----+----------+
| 9 | 83 | 11:12:00 | 10 | 25 | 11:15:00 |
| 8 | 90 | 11:09:00 | 9 | 83 | 11:12:00 |
| 7 | 24 | 11:06:00 | 8 | 90 | 11:09:00 |
| 6 | 29 | 11:03:00 | 7 | 24 | 11:06:00 |
| 5 | 72 | 11:00:00 | 6 | 29 | 11:03:00 |
| 4 | 28 | 10:57:00 | 5 | 72 | 11:00:00 |
| 3 | 22 | 10:54:00 | 4 | 28 | 10:57:00 |
| 2 | 42 | 10:51:00 | 3 | 22 | 10:54:00 |
| 1 | 35 | 10:48:00 | 2 | 42 | 10:51:00 |
| 0 | 31 | 10:45:00 | 1 | 35 | 10:48:00 |
+------------+----+----------+------------+----+----------+
Based on this table, I calculate the integral value in a single query as:
select sum(v) from
(select (a.v + b.v)/2 * (TIME_TO_SEC(b.t) - TIME_TO_SEC(a.t))/3600 as v from
(select measure_id, v, t from p_values order by t desc) a,
(select measure_id, v, t from p_values order by t desc) b
where a.t < b.t group by b.t desc) as c;
+---------+
| sum(v) |
+---------+
| 246.948 |
+---------+
But I'm not sure if this is the most efficient way to do this.
Thanks.
If you assume that the measure_id is incremental with no gaps, then you can do this with a self join. The resulting query is something like this:
select sum(p1.v*(p2.t - p1.t))
from p_values p1 join
p_values p2
on p2.measure_id = p1.measure_id + 1;
A couple of notes. First, this ignores the last v value, because there is no matching row. The question doesn't specify what to do in this case, so I assume you don't want that difference included.
I also left the simple notation for difference of times. Your question appears to be about handling the values from different rows, not actually calculating the difference of the time column. That, in turn, depends on the data type for the column, which is not specified in the question.
Finally, your subquery has a fatal flaw. It has columns in the select that are not in the group by. This uses a group by extension that the documentation explicitly warns against using.
select sum(value)
from
(select (p.v*(t-#prev)) as value,
#prev:=t
from (select #prev:=0) sess, p_values p
order by p.measure_id desc) raw
Here we introduce a variable #prev where we store value from previous row (but we sort in desc order).
Then just sum the results
UPDATE query for the fiddle
select sum(value)
from
(select (p.v*(t-#prev)) as value,
#prev:=v
from (select #prev:=0) sess, p_values p
order by v desc) raw

MySQL count rows with similar timestamp

Is there anyway to count a given run of timestamps that are close to each other, but not necessarily in a fixed time frame?
Ie, not grouped by hour or minute, but rather grouped by how close the current row's timestamp is to the next row's timestamp. If the next row is within "x" seconds/minutes then add that row to the group, otherwise start a new grouping.
Given this data:
+----+---------+---------------------+
| id | item_id | event_date |
+----+---------+---------------------+
| 1 | 1 | 2013-05-17 11:59:59 |
| 2 | 1 | 2013-05-17 12:00:00 |
| 3 | 1 | 2013-05-17 12:00:02 |
| 4 | 1 | 2013-05-17 12:00:03 |
| 5 | 3 | 2013-05-17 14:05:00 |
| 6 | 3 | 2013-05-17 14:05:01 |
| 7 | 3 | 2013-05-17 15:30:00 |
| 8 | 3 | 2013-05-17 15:30:01 |
| 9 | 3 | 2013-05-17 15:30:02 |
| 10 | 1 | 2013-05-18 09:12:00 |
| 11 | 1 | 2013-05-18 09:13:30 |
| 12 | 1 | 2013-05-18 09:13:45 |
| 13 | 1 | 2013-05-18 09:14:00 |
| 14 | 2 | 2013-05-20 15:45:00 |
| 15 | 2 | 2013-05-20 15:45:03 |
| 16 | 2 | 2013-05-20 15:45:10 |
| 17 | 2 | 2013-05-23 07:36:00 |
| 18 | 2 | 2013-05-23 07:36:10 |
| 19 | 2 | 2013-05-23 07:36:12 |
| 20 | 2 | 2013-05-23 07:36:15 |
| 21 | 1 | 2013-05-24 11:55:00 |
| 22 | 1 | 2013-05-24 11:55:02 |
+----+---------+---------------------+
Desired Results:
+---------+-------+---------------------+
| item_id | total | last_date_in_group |
+---------+-------+---------------------+
| 1 | 4 | 2013-05-17 12:00:03 |
| 3 | 2 | 2013-05-17 14:05:01 |
| 3 | 3 | 2013-05-17 15:30:02 |
| 1 | 4 | 2013-05-18 09:14:00 |
| 2 | 3 | 2013-05-20 15:45:10 |
| 2 | 4 | 2013-05-23 07:36:15 |
| 1 | 2 | 2013-05-24 11:55:02 |
+---------+-------+---------------------+
This is a little complicated. To start, you need is time of the next event for each record. The following subquery adds in such a time (nexted), if it is within bounds:
select t.*,
(select event_date
from t t2
where t2.item_id = t.item_id and
t2.event_date > t.event_date and
<date comparison here>
order by event_date limit 1
) as nexted
from t
This uses a correlated subquery. The <date comparison here> is for whatever date comparison you want. When there is no record, the value will be NULL.
Now, with this information (nexted) there is a trick to get the grouping. For any record, it is the first event time afterwards where nexted is NULL. This will be the last event in the series. Unfortunately, this requires two levels of nested correlated subqueries (or joins with aggregations). The result looks a bit unwieldy:
select item_id, GROUPING, MIN(event_date) as start_date, MAX(event_date) as end_date,
COUNT(*) as num_dates
from (select t.*,
(select min(t2.event_date)
from (select t1.*,
(select event_date
from t t2
where t2.item_id = t1.item_id and
t2.event_date > t1.event_date and
<date comparison here>
order by event_date limit 1
) as nexted
from t1
) t2
where t2.nexted is null
) as grouping
from t
) s
group by item_id, grouping;
What about approaching it from finding each individual record's local associations, and then grouping on the max event date from each record's discoveries. This is based on a static differential time interval (5 minutes in my example)
SELECT item_id, MAX(total), MAX(last_date_in_group) AS last_date_in_group FROM (
SELECT t1.item_id, COUNT(*) AS total, COALESCE(GREATEST(t1.event_date, MAX(t2.event_date)), t1.event_date) AS last_date_in_group
FROM table_name t1
LEFT JOIN table_name t2 ON t2.event_date BETWEEN t1.event_date AND t1.event_date + INTERVAL 5 MINUTE
GROUP BY t1.id
) t
GROUP BY last_date_in_group

MySQL combine results from UNION of same-scheme tables

There are two tables with the same structure: 'imsc_storage_users' & 'imsc_storage_users_archive'.
My current SELECT/UNION:
SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users`
UNION DISTINCT
SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users_archive`
ORDER BY `correct` DESC,`minutes` ASC
I'm getting these results:
+--------------+---------------------+-----------+---------+---------+------+---------+
| cli | ts | questions | answers | correct | last | minutes |
+--------------+---------------------+-----------+---------+---------+------+---------+
| 111111111111 | 2011-12-22 11:13:57 | 30 | 29 | 14 | 30 | 1305.47 |
| 222222222222 | 2011-12-15 13:39:16 | 26 | 24 | 13 | 24 | 15.67 |
| 333333333333 | 2011-12-15 13:39:39 | 26 | 25 | 11 | 25 | 15.18 |
| 444444444444 | 2011-12-15 13:39:39 | 25 | 21 | 11 | 25 | 280.53 |
| 111111111111 | 2011-12-22 11:13:57 | 25 | 21 | 10 | 25 | 373.87 |
| 555555555555 | 2011-12-19 15:46:15 | 11 | 10 | 5 | 10 | 3.8 |
| 666666666666 | 2011-12-15 13:39:16 | 14 | 10 | 4 | 10 | 321.64 |
| 777777777777 | 2011-12-19 08:34:36 | 15 | 11 | 4 | 13 | 474.66 |
Notice that '111111111111' appears twice?
I want it to be combined, so in the results set I get one row of '111111111111' which combines/sums all fields; 'questions' =>> 55.... etc'.
What would be the correct SQL?
Performance are NOT of an issue here.
Thank you!
SELECT `cli`,max(`ts`) AS ts, sum(`questions`) as questions, sum(`answers`) as answers,sum(`correct`) as correct,sum(`last`) as last,sum(`minutes`) as minutes
FROM (
SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users`
UNION ALL
SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users_archive`
) AS baseview
GROUP BY cli
ORDER BY `correct` DESC,`minutes` ASC
Try:
SELECT `cli`,
`ts`,
sum(`questions`),
sum(`answers`),
sum(`correct`),
sum(`last`),
sum(`minutes`)
FROM (SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users`
UNION ALL
SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users_archive`) V
group by `cli`, `ts`
ORDER BY 5 DESC, 7 ASC