Getting ROW_NUMBER in MySQL, restarting at 1 for sub-groups? - mysql

I have a database table containing responses to questions from users. Each question has a request and a response timestamp. The questions are asked in random order. Some users abandoned before completing all the questions and thus don't have subsequent response records.
I didn't capture the order in which the questions were asked for each user, but the sequence could be derived from the request timestamps (SELECT * FROM responses ORDER BY id_user, request_ts;).
I'm using MySQL, so I don't have ROW_NUMBER() as an available function. How would I go about getting the equivalent output, and have the counting restart on each id_user?
That is, for user_id=1, I want responses with values 1,2,..n ordered by request_ts, and then user_id=2 would have their responses with values 1,2,..n; and so on.
Ultimately, I want to get a set of data of aggregated average duration for each nth question (i.e. average duration for first question asked, ditto second question asked, etc).
+-----+-----+-------+
| Seq | Num | Avg_D |
+-----+-----+-------+
| 1 | 20 | 00:36 |
| 2 | 20 | 00:31 |
| 3 | 19 | 00:31 |
| 4 | 20 | 00:25 |
| 5 | 18 | 00:24 |
| 6 | 20 | 00:24 |
| 7 | 20 | 00:23 |
| 8 | 20 | 00:25 |
+-----+-----+-------+
This can then be used to show participant drop-off, survey fatigue, etc.

I created a dummy with sample data.
CREATE TABLE `test9b` ( `id` int(32) NOT NULL AUTO_INCREMENT, `user_id` int(32) NOT NULL, `num` int(32) NOT NULL, `avg` int(32) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8
INSERT INTO `test9b` (`id`, `user_id`, `num`, `avg`) VALUES
(1, 1, 21, 36),
(2, 1, 23, 32),
(3, 1, 20, 35),
(4, 2, 22, 32),
(5, 2, 25, 37),
(6, 2, 10, 39),
(7, 2, 20, 33),
(8, 3, 30, 36),
(9, 3, 40, 36),
(10, 4, 50, 36);
Query :
SELECT a.user_id, a.num, count(*) as row_number FROM test9b a
JOIN test9b b ON a.user_id = b.user_id AND a.num >= b.num
GROUP BY a.user_id, a.num
OUTPUT :
user_id num row_number
1 20 1
1 21 2
1 23 3
2 10 1
2 20 2
2 22 3
2 25 4
3 30 1
3 40 2
4 50 1

Related

Sort records on multiple columns and conditions

I have the below table, that stores the rank of person participating in respective events.
event_running and event_jumping are the events and the ranks stored.
CREATE TABLE `ranks` (
`id` int(11) NOT NULL,
`personid` int(11) NOT NULL,
`event_running` int(11) DEFAULT NULL,
`event_longjump` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Sample data
INSERT INTO `ranks` (`id`, `personid`, `event_running`, `event_longjump`) VALUES
(1, 1, 4, 8),
(2, 2, 10, 6),
(3, 3, 5, 0),
(4, 5, 20, 1),
(5, 4, 9, 3),
(6, 6, 1, 2);
SQL Fiddle Link
I want to build a leaderboard as below
| Standing | PersonID | RunningRank | JumpingRank |
| 1 | 6 | 1 | 2 |
| 2 | 4 | 9 | 3 |
| 3 | 1 | 4 | 8 |
| 4 | 3 | 5 | 0 |
| 5 | 2 | 10 | 6 |
This has to be sorted in ascending order - irrespective of the events lowest come first and also ranks above 20 are ignored.
And inputs on how can this be done?
you can use something similar to below
select PersonID,
RunningRank,
JumpingRank,
(RunningRank + JumpingRank) as Total
from ranks
order by Total asc
limit 20;
Here's your query.
set #row_number = 0;
select (#row_number:=#row_number + 1) as standing, personid, event_running, event_longjump from ranks
where event_running < 20 and event_longjump < 20
order by
case when if(event_longjump=0,event_running ,event_longjump) < event_running
then event_longjump else event_running end
see dbfiddle
Your sorting criteria is a bit vague. I am assuming that you want to sort on the basis of cumulative of the ranks across all events and its jumping score.
Also, please explain the position of person Id 3 in your queation.
You can do,
select PersonID,
RunningRank,
JumpingRank,
(JumpingRank + RunningRank) as cumulativeRank
from ranks
ORDER BY cumulativeRank, JumpingRank aesc
limit 20;
This will get you all the positions baring person id 3

How to make Mysql variables work in a query

I've been struggling for a while now with attempting to generate code for automatic aggregations in my mysql/mariadb database. The method That i'm currently trying uses variables. I will admit in advance I'm not a database expert by any means. I'm totally self taught, and have been struggling to find adequate resources for this particular problem. Ive included simplified examples below, Oh and i'm using mariadb 10.1.
This code should work in mysql 5.6 as well as mariadb 10.0+, I have tested it on 10.1 and it works.
Here is my Table: and SQL FIDDLE <- doesn't work for some reason. Probably the dynamic columns. I'll leave it in case someone knows why.
CREATE TABLE data_points
(
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
device_id INTEGER,
dtime DATETIME,
sf INTEGER(11), -- sample frequency or interval
agg INTEGER(11), -- aggregation type, actually a fk
data_point BLOB,
PRIMARY KEY (id),
UNIQUE (device_id, dtime, sf, agg)
);
Lets insert some data:
INSERT INTO data_points
(device_id, dtime, sf, agg, data_point)
VALUES
(1, '2015-01-02 12:00:00', 1, 60, COLUMN_CREATE('aa', 12, 'ab', 34, 'ac', 45)),
(1, '2015-01-02 13:00:00', 1, 60, COLUMN_CREATE('aa', 12, 'ab', 34, 'ac', 45)),
(1, '2015-01-02 14:00:00', 1, 60, COLUMN_CREATE('aa', 12, 'ab', 34, 'ac', 45)),
(1, '2015-01-02 15:00:00', 1, 60, COLUMN_CREATE('aa', 12, 'ab', 34, 'ac', 45)),
(1, '2015-01-02 16:00:00', 1, 60, COLUMN_CREATE('aa', 12, 'ab', 34, 'ac', 45));
So up to this point everything works just fine. What i'm trying to do is perform aggregations over different time periods, my lowest grain period is 60 seconds. Here is where I have issues, Its probably something obvious.
SELECT
#dp_dtime := MAX(dtime),
#dp_aa := MIN(ROUND(COLUMN_GET(data_point, 'aa' AS DOUBLE), 4)),
#dp_ab := MIN(ROUND(COLUMN_GET(data_point, 'ab' AS DOUBLE), 4)),
#dp_ac := MIN(ROUND(COLUMN_GET(data_point, 'ac' AS DOUBLE), 4))
FROM data_points
WHERE
device_id = 1 AND
dtime BETWEEN '2015/01/02 12:00:00' AND '2015/01/17 23:05:00' AND
sf = 60 AND
agg = 1;
INSERT INTO data_points
(device_id, dtime, sf, agg, data_point)
VALUES (8, #dp_dtime, 300, 2, COLUMN_CREATE('aa', #dp_aa, 'ab', #dp_ab, 'ac', #dp_ac));
This ends up creating another row with NULL everywhere a variable was in the statement.
select #dp_dtime, #dp_aa, #dp_ab, #pd_ac;
-- This results in NULL, NULL, NULL, NULL
At this point I'm pretty sure i'm doing something wrong with the variables.
It's Late, 14 hour day. Am I even close? Is there a better/easier way?
Any help would be greatly appreciated.
EDIT:
In my real use case the number of columns is dependent on the type of device were doing an aggregation for. Columns are excel style 'aa' through 'zz' possible. although the max I've seen is about 150 cols wide. This may sound like a bad design, but the performance is surprising, I can't tell the difference between these dynamic columns and actual columns. (at least as long as you don't need to index on them)
Try the following queries.
SQL:
CREATE TABLE data_points
(
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
device_id INTEGER,
dtime DATETIME,
sf INTEGER(11), -- sample frequency or interval
agg INTEGER(11), -- aggregation type, actually a fk
data_point BLOB,
UNIQUE (device_id, dtime, sf, agg)
);
INSERT INTO data_points
(device_id, dtime, sf, agg, data_point)
VALUES
(1, '2015-01-02 12:00:00', 1, 1, COLUMN_CREATE('aa', 12, 'ab', 34, 'ac', 45)),
(1, '2015-01-02 13:00:00', 1, 1, COLUMN_CREATE('aa', 12, 'ab', 34, 'ac', 45)),
(1, '2015-01-02 14:00:00', 1, 1, COLUMN_CREATE('aa', 12, 'ab', 34, 'ac', 45)),
(1, '2015-01-02 15:00:00', 1, 1, COLUMN_CREATE('aa', 12, 'ab', 34, 'ac', 45)),
(1, '2015-01-02 16:00:00', 1, 1, COLUMN_CREATE('aa', 12, 'ab', 34, 'ac', 45));
select * from data_points;
SELECT
#dp_dtime := MAX(dtime) as dp_dtime,
#dp_aa := MIN(ROUND(COLUMN_GET(data_point, 'aa' AS DOUBLE), 4)) as dp_aa,
#dp_ab := MIN(ROUND(COLUMN_GET(data_point, 'ab' AS DOUBLE), 4)) as dp_ab,
#dp_ac := MIN(ROUND(COLUMN_GET(data_point, 'ac' AS DOUBLE), 4)) as dp_ac
FROM data_points
WHERE
device_id = 1 AND
dtime BETWEEN '2015/01/02 12:00:00' AND '2015/1/17 23:05:00' AND
sf = 1 AND
agg = 1;
INSERT INTO data_points
(device_id, dtime, sf, agg, data_point)
VALUES (8, #dp_dtime, 300, 2, COLUMN_CREATE('aa', #dp_aa, 'ab', #dp_ab, 'ac', #dp_ac));
select * from data_points;
Output:
mysql> select * from data_points;
+----+-----------+---------------------+------+------+----------------------------+
| id | device_id | dtime | sf | agg | data_point |
+----+-----------+---------------------+------+------+----------------------------+
| 1 | 1 | 2015-01-02 12:00:00 | 1 | 1 | aaabacDZ |
| 2 | 1 | 2015-01-02 13:00:00 | 1 | 1 | aaabacDZ |
| 3 | 1 | 2015-01-02 14:00:00 | 1 | 1 | aaabacDZ |
| 4 | 1 | 2015-01-02 15:00:00 | 1 | 1 | aaabacDZ |
| 5 | 1 | 2015-01-02 16:00:00 | 1 | 1 | aaabacDZ |
+----+-----------+---------------------+------+------+----------------------------+
5 rows in set (0.00 sec)
mysql> SELECT
-> #dp_dtime := MAX(dtime) as dp_dtime,
-> #dp_aa := MIN(ROUND(COLUMN_GET(data_point, 'aa' AS DOUBLE), 4)) as dp_aa,
-> #dp_ab := MIN(ROUND(COLUMN_GET(data_point, 'ab' AS DOUBLE), 4)) as dp_ab,
-> #dp_ac := MIN(ROUND(COLUMN_GET(data_point, 'ac' AS DOUBLE), 4)) as dp_ac
-> FROM data_points
-> WHERE
-> device_id = 1 AND
-> dtime BETWEEN '2015/01/02 12:00:00' AND '2015/1/17 23:05:00' AND
-> sf = 1 AND
-> agg = 1;
+---------------------+---------+---------+---------+
| dp_dtime | dp_aa | dp_ab | dp_ac |
+---------------------+---------+---------+---------+
| 2015-01-02 16:00:00 | 12.0000 | 34.0000 | 45.0000 |
+---------------------+---------+---------+---------+
1 row in set (0.00 sec)
mysql> INSERT INTO data_points
-> (device_id, dtime, sf, agg, data_point)
-> VALUES (8, #dp_dtime, 300, 2, COLUMN_CREATE('aa', #dp_aa, 'ab', #dp_ab, 'ac', #dp_ac));
Query OK, 1 row affected (0.00 sec)
mysql> select * from data_points;
+----+-----------+---------------------+------+------+-------------------------------------------------+
| id | device_id | dtime | sf | agg | data_point |
+----+-----------+---------------------+------+------+-------------------------------------------------+
| 1 | 1 | 2015-01-02 12:00:00 | 1 | 1 | aaabacDZ |
| 2 | 1 | 2015-01-02 13:00:00 | 1 | 1 | aaabacDZ |
| 3 | 1 | 2015-01-02 14:00:00 | 1 | 1 | aaabacDZ |
| 4 | 1 | 2015-01-02 15:00:00 | 1 | 1 | aaabacDZ |
| 5 | 1 | 2015-01-02 16:00:00 | 1 | 1 | aaabacDZ |
| 6 | 8 | 2015-01-02 16:00:00 | 300 | 2 | ▒ aaabac (# A# ▒F# |
+----+-----------+---------------------+------+------+-------------------------------------------------+
6 rows in set (0.00 sec)
Possibly a simple typo: I see #_dtime.
In the UNIQUE index, put dtime last; it will make the queries faster. Mini index lesson: All = columns should come first in a composite index, in any order (cardinality makes virtually no difference). Then you can put one 'range' (dtime). Any columns after a range are not used for filtering. See my cookbook.
Get rid of id and promote the UNIQUE index to PRIMARY KEY; it will make the queries still faster. Mini index lesson: Secondary keys (such as your UNIQUE) requires bouncing between the key and the data. The PRIMARY KEY is clustered with the data (in InnoDB), thereby avoiding the bouncing. Instead a 'range scan' over the PK is a range over the table.

How do I store a value from the last row in a variable using MySQL?

I am trying to calculate the date difference between each record in a dataset for each account.
Here is the data that I have
id aid value
1 1 2015-01-01
2 1 2015-01-07
4 1 2015-01-08
6 1 2015-04-10
3 2 2015-02-01
5 2 2015-02-05
I would first need to combine the data where I can use TIMESTAMPDIFF to calculate the difference in Days (i.e. TIMESTAMPDIFF(DAY, previousValue, currentValue)).
How can I combine the rows in the dataset about to look like this
aid currentValue previousValue
1 2015-01-07 2015-01-01
1 2015-01-08 2015-01-07
1 2015-04-10 2015-01-08
2 2015-02-05 2015-02-01
from there I can easily calculate the difference in days between current and previous value.
Note, that I have a large data set and I can't use subqueries in my select this is why I need to know how to do it using variables.
How can convert my initial dataset to the second dataset where I have currentValue, previousValue for each account?
Here is SQL to generate tables with the data above
CREATE TEMPORARY TABLE lst
(
id int,
account_id int,
value date
);
INSERT INTO lst VALUES
(1, 1, '2015-01-01')
, (2, 1, '2015-01-07')
, (3, 2, '2015-02-01')
, (4, 1, '2015-01-08')
, (5, 2, '2015-02-05')
, (6, 1, '2015-04-10');
CREATE TEMPORARY TABLE lst1 AS
SELECT * FROM lst ORDER BY account_id, value ASC;
UPDATED
This is what I get after attempting Giorgos Betsos' answer below
'1', '2015-01-01', '2015-01-07'
'1', '2015-01-07', '2015-01-08'
'1', '2015-02-05', '2015-04-10'
'2', '2015-01-08', '2015-02-01'
'2', '2015-02-01', '2015-02-05'
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE test
(
id int,
account_id int,
value date
);
INSERT INTO test VALUES
(1, 1, '2015-01-01')
, (2, 1, '2015-01-07')
, (3, 2, '2015-02-01')
, (4, 1, '2015-01-08')
, (5, 2, '2015-02-05')
, (6, 1, '2015-04-10');
Query 1:
SELECT
IF(#accId = account_id, #prevDate, '-') as "Previous Date",
(#prevDate := value) as "Date",
(#accId :=account_id) as account_id
FROM
test, (SELECT #accId := 0) a, (SELECT #prevDate := '-') b
ORDER BY account_id ASC, value ASC
Results:
| Previous Date | Date | account_id |
|---------------|------------|------------|
| - | 2015-01-01 | 1 |
| 2015-01-01 | 2015-01-07 | 1 |
| 2015-01-07 | 2015-01-08 | 1 |
| 2015-01-08 | 2015-04-10 | 1 |
| - | 2015-02-01 | 2 |
| 2015-02-01 | 2015-02-05 | 2 |

MySQL - get min and max values for id's in group [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Updated:
TABLE: mydata
id trans_id CURRENT CUST_DATE
------------------------------------
16 2362 152.40 2015-05-11
16 2363 146.80 2015-05-26
16 1669 147.00 2015-06-16
16 1979 148.60 2015-07-06
16 2344 144.00 2015-08-06
104 1280 161.40 2015-05-29
104 1553 158.20 2015-06-10
104 1898 158.20 2015-06-29
104 2131 158.20 2015-07-15
104 2223 158.20 2015-07-27
104 2294 158.20 2015-08-03
I need a query that will return the first and last value for CURRENT within each group of ID's based on CUST_DATE.
Couple of items to point out:
I'm only showing two ID's in this example. The real table has thousands of distinct ID's.
trans_id is an auto incremented field. My initial query had max(trans_id) and min(trans_id)...which worked until a new row was added with an earlier date value and caused the natural ascending order to become out-of-wack. You can see this issue on ID 16 in the table above.
I've been noodling with this seemingly simple query for two days now...just can't wrap my head around it.
Expected output (flat structure):
id CURRENT_MAX CURRENT_MIN
-------------------------------
16 152.40 144.00
104 161.40 158.20
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE mydata
(`id` int, `trans_id` int, `CURRENT` double, `CUST_DATE` datetime)
;
INSERT INTO mydata
(`id`, `trans_id`, `CURRENT`, `CUST_DATE`)
VALUES
(16, 2362, 152.40, '2015-05-11 00:00:00'),
(16, 2363, 146.80, '2015-05-26 00:00:00'),
(16, 1669, 147.00, '2015-06-16 00:00:00'),
(16, 1979, 148.60, '2015-07-06 00:00:00'),
(16, 2344, 144.00, '2015-08-06 00:00:00'),
(104, 1280, 161.40, '2015-05-29 00:00:00'),
(104, 1553, 158.20, '2015-06-10 00:00:00'),
(104, 1898, 158.20, '2015-06-29 00:00:00'),
(104, 2131, 158.20, '2015-07-15 00:00:00'),
(104, 2223, 158.20, '2015-07-27 00:00:00'),
(104, 2294, 158.20, '2015-08-03 00:00:00')
;
Query 1:
SELECT id, MIN(CURRENT), MAX(CURRENT)
FROM mydata
GROUP BY ID
Results:
| id | MIN(CURRENT) | MAX(CURRENT) |
|-----|--------------|--------------|
| 16 | 144 | 152.4 |
| 104 | 158.2 | 161.4 |
Several rows share the same minimum current, so I assume you want all of them as you've not specified otherwise...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL
, trans_id INT NOT NULL
,CURRENT DECIMAL(5,2)
,CUST_DATE DATE NOT NULL
);
INSERT INTO my_table VALUES
(16 ,2362 ,152.40 ,'2015-05-11'),
(16 ,2363 ,146.80 ,'2015-05-26'),
(16 ,1669 ,147.00 ,'2015-06-16'),
(16 ,1979 ,148.60 ,'2015-07-06'),
(16 ,2344 ,144.00 ,'2015-08-06'),
(104 ,1280 ,161.40 ,'2015-05-29'),
(104 ,1553 ,158.20 ,'2015-06-10'),
(104 ,1898 ,158.20 ,'2015-06-29'),
(104 ,2131 ,158.20 ,'2015-07-15'),
(104 ,2223 ,158.20 ,'2015-07-27'),
(104 ,2294 ,158.20 ,'2015-08-03');
SELECT a.*
FROM my_table a
JOIN
(
SELECT id, MAX(current) x_current FROM my_table GROUP BY id
UNION
SELECT id, MIN(current) x_current FROM my_table GROUP BY id
) b
ON b.id = a.id AND b.x_current = a.current;
+-----+----------+---------+------------+
| id | trans_id | CURRENT | CUST_DATE |
+-----+----------+---------+------------+
| 16 | 2362 | 152.40 | 2015-05-11 |
| 16 | 2344 | 144.00 | 2015-08-06 |
| 104 | 1280 | 161.40 | 2015-05-29 |
| 104 | 1553 | 158.20 | 2015-06-10 |
| 104 | 1898 | 158.20 | 2015-06-29 |
| 104 | 2131 | 158.20 | 2015-07-15 |
| 104 | 2223 | 158.20 | 2015-07-27 |
| 104 | 2294 | 158.20 | 2015-08-03 |
+-----+----------+---------+------------+
or
SELECT a.*
FROM my_table a
JOIN
(
SELECT id
, MAX(current) max_current
, MIN(current) min_current
FROM my_table
GROUP
BY id
) b
ON b.id = a.id AND a.current IN (b.max_current,b.min_current);
Since this question was first asked, the specification has changed significantly. The new requirement is too obvious to bother with.

GROUP BY and SUM distinct date across 2 tables

I'm not sure if this is possible in one mysql query so I might just combine the results via php.
I have 2 tables: 'users' and 'billing'
I'm trying to group summed activity for every date that is available in these two tables. 'users' is not historical data but 'billing' contains a record for each transaction.
In this example I am showing a user's status which I'd like to sum for created date and deposit amounts that I would also like to sum by created date. I realize there is a bit of a disconnect between the data but I'd like to some all of it together and display it as seen below. This will show me an overview of all of the users by when they were created and what the current statuses are next to total transactions.
I've tried UNION as well as LEFT JOIN but I can't seem to get either to work.
Union example is pretty close but doesn't combine the dates into one row.
(
SELECT
created,
SUM(status) as totalActive,
NULL as totalDeposit
FROM users
GROUP BY created
)
UNION
(
SELECT
created,
NULL as totalActive,
SUM(transactionAmount) as totalDeposit
FROM billing
GROUP BY created
)
I've also tried using a date lookup table and joining on the dates but the SUM values are being added multiple times.
note: I don't care about the userIds at all but have it in here for the example.
users table
(where status of '1' denotes "active")
(one record for each user)
created | userId | status
2010-03-01 | 10 | 0
2010-03-01 | 11 | 1
2010-03-01 | 12 | 1
2010-03-10 | 13 | 0
2010-03-12 | 14 | 1
2010-03-12 | 15 | 1
2010-03-13 | 16 | 0
2010-03-15 | 17 | 1
billing table
(record created for every instance of a billing "transaction"
created | userId | transactionAmount
2010-03-01 | 10 | 50
2010-03-01 | 18 | 50
2010-03-01 | 19 | 100
2010-03-10 | 89 | 55
2010-03-15 | 16 | 50
2010-03-15 | 12 | 90
2010-03-22 | 99 | 150
desired result:
created | sumStatusActive | sumStatusInactive | sumTransactions
2010-03-01 | 2 | 1 | 200
2010-03-10 | 0 | 1 | 55
2010-03-12 | 2 | 0 | 0
2010-03-13 | 0 | 0 | 0
2010-03-15 | 1 | 0 | 140
2010-03-22 | 0 | 0 | 150
Table dump:
CREATE TABLE IF NOT EXISTS `users` (
`created` date NOT NULL,
`userId` int(11) NOT NULL,
`status` smallint(6) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `users` (`created`, `userId`, `status`) VALUES
('2010-03-01', 10, 0),
('2010-03-01', 11, 1),
('2010-03-01', 12, 1),
('2010-03-10', 13, 0),
('2010-03-12', 14, 1),
('2010-03-12', 15, 1),
('2010-03-13', 16, 0),
('2010-03-15', 17, 1);
CREATE TABLE IF NOT EXISTS `billing` (
`created` date NOT NULL,
`userId` int(11) NOT NULL,
`transactionAmount` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `billing` (`created`, `userId`, `transactionAmount`) VALUES
('2010-03-01', 10, 50),
('2010-03-01', 18, 50),
('2010-03-01', 19, 100),
('2010-03-10', 89, 55),
('2010-03-15', 16, 50),
('2010-03-15', 12, 90),
('2010-03-22', 99, 150);
Try this:
Select created, sum(status) as totalActive, sum(transactionAmount) as totalDeposit
From
( (
SELECT
created,
status,
0 as transactionAmount
FROM users
)
UNION
(
SELECT
created,
0 as status,
transactionAmount
FROM billing
) ) as x group by created
Ah. Thanks to p.g.I.hall I was able to modify the query and get my desired result:
Select
createdDate,
SUM(statusSum),
SUM(transactionAmountSum)
From
( (
SELECT
created as createdDate,
sum(status) as statusSum,
'0' as transactionAmountSum
FROM users
GROUP BY createdDate
)
UNION
(
SELECT
created as createdDate,
'0' as statusSum,
sum(transactionAmount) as transactionAmountSum
FROM billing
GROUP BY createdDate
) )
as x
group by createdDate
A word of warning - your users table does not have a unique key. I'm going to take a wild guess here and say that you should probably create a primary key with the userId column.
A table without primary keys means you have no protection against bad, duplicate data slipping into your tables! Aaaaaah!