I doubt it can be right to solve.
test_table:
id | name | value | date
---------|---------|---------|------------
1 | john | 32 | 2016-01-08
2 | tom | 590 | 2016-01-03
3 | king | 1903 | 2016-01-01
4 | john | 490 | 2016-01-02
5 | gary | 58 | 2016-01-18
6 | cat | 5 | 2016-01-10
sql1:
select name,sum(value) as val from test_table where val > 500 group by name;
sql2:
select name from test_table where date >= DATE_SUB(CURDATE(),INTERVAL 1 WEEK) group by name;
I want combine two sql in one. The sql result name is not exists in sql2 name result collection.
update:
sorry for my confused describe.
The sql1 is scan whole the table, it aim to find out who's total value is greater than 500.
The sql2 is scan last week's data to find out who exists last week.
So, I Want combine two sql , to find out those people who's total value is greater than 500 but not exists last week.
sorry again for my poor English.
update - add example:
just like the table content,the result should be :
john,tom,king
because their total value is > 500,but not update last week
But how can I do it.
Thanks all.
SELECT name, sum(value)
FROM test_table
WHERE value > 500
AND name NOT IN (
SELECT name
FROM test_table
WHERE `date` >= DATE_SUB(CURDATE(), INTERVAL 1 WEEK)
)
GROUP BY 1
OR
SELECT name, sum(value)
FROM test_table
WHERE value > 500
GROUP BY 1
HAVING max(`date') < DATE_SUB(CURDATE(), INTERVAL 1 WEEK)
If you are trying to having sum(value) > 500, delete above lines
WHERE value > 500
And change AND to WHERE for the first SQL
And add this line at end of each of above:
having sum(value) > 500
It is really helpful to describe what you want, as well as providing SQL samples. You seem to want the sum of values greater than 500 for names that have no row with date in the past week.
If so:
select name, sum(case when value > 500 then value else 0 end)
from test_table
where value > 500
group by name
having max(date) < DATE_SUB(CURDATE(), INTERVAL 1 WEEK) ;
Related
Unable to get total per accountcode, it gives me a sum of all, here is the code
SELECT cdr.accountcode,
(SELECT COUNT(id) FROM cdr WHERE cdr.calldate > now() - INTERVAL 30 MINUTE and cdr.dstchannel LIKE '%neural%') AS callcount ,
(SELECT COUNT(id) FROM cdr WHERE cdr.calldate > now() - INTERVAL 3 MINUTE and cdr.dstchannel LIKE '%neotel%') AS localcallcount
FROM cdr
Table Structure
id | calldate | clid | src | dst | dstchannel | accountcode | note
---+------------+-------+-----+-----------------+------------+-------------+------
12 | 2018-12-05 | "105" | 105 | SIP/neotel/1234 | 1234user | testuser | null
Expected output
accountcode callcount localcallcount
5000user 1 2
5236user 1 3
Use SUM() instead of COUNT(). COUNT() counts every line, no matter what. The boolean expression in the SUM() function returns either 1 or 0, depending on if it's true or false.
SELECT cdr.accountcode,
SUM(cdr.calldate > now() - INTERVAL 30 MINUTE and cdr.dstchannel LIKE '%neural%') AS callcount ,
SUM(cdr.calldate > now() - INTERVAL 3 MINUTE and cdr.dstchannel LIKE '%neotel%') AS localcallcount
FROM cdr
I have a table containing log entries that looks like this:
id | name | level | timestamp
5 | ironman | 35 | 2019-01-06 11:37:40
6 | ironman | 35 | 2019-01-06 11:38:40
7 | ironman | 36 | 2019-01-06 11:39:40
8 | superman | 25 | 2019-01-06 11:39:49
I need help making a query that returns a list of levels gained the last X hours for each character, preferably sorted by amount gained.
So by this example my wanted result is this
id | name | gained | timestamp
7 | ironman | 1 | 2019-01-06 11:37:40
8 | superman | 0 | 2019-01-06 11:37:40
You need to join the main table with a query that calculates the change in levels:
select levels.id, t.name, t.gained, t.timestamp
from (
select
name,
max(level) - min(level) gained,
max(timestamp) timestamp
from levels
where timestamp > now() - interval 10 hour
group by name
) t inner join levels
on
t.timestamp = levels.timestamp
and
t.name = levels.name
where levels.timestamp > now() - interval 10 hour
order by t.gained desc, t.name
I guess the timestamp in the expected output you posted about superman is wrong and it should be 2019-01-06 11:39:49.
See the demo
Try an aggregate query that compares the MIN and MAX level of each character :
SELECT
name,
MAX(level) - MIN(level) as gained,
MIN(timestamp)
FROM mytable
WHERE timestamp > NOW() - INTERVAL 1 HOUR
GROUP BY
name
ORDER BY
gained desc
NB : this assumes that the level of a character may only increase. If the level of a character decreases, it will still appear as a gain.
I have a table with the following data (merely an example, actual table has 600,000 rows) (aid = access id [primary key] and id = user id [foreign key]):
aid | id | date
332 | 1 | 2016-12-15
331 | 4 | 2016-12-15
330 | 3 | 2016-12-15
329 | 1 | 2016-12-14
328 | 1 | 2016-12-14
327 | 2 | 2016-12-14
326 | 3 | 2016-12-13
325 | 2 | 2016-12-13
324 | 1 | 2016-12-13
323 | 1 | 2016-12-12
322 | 3 | 2016-12-12
321 | 1 | 2016-12-12
Each id is a users primary key, and every time they access something in my system I log them in this table (with the date in the format as shown, and their id). A user can be logged multiple times a day.
I'm looking to: return the total number of times the thing has been accessed in a day and return the total number of NEW users who have accessed the thing in a day, for the last 8 days (something will always be logged each day, so using "LIMIT 8" is fine for getting only the last 8 days).
My SQL currently looks like:
SELECT COUNT(id), COUNT(distinct id), date
FROM table
GROUP BY date
ORDER BY date DESC
LIMIT 8;
That SQL does the first part correctly, but I can't figure out how to get it to return the number of users who have never accessed the thing until that day.
Desired results would be, the one "newuser" represents the user with id "4" as they have never accessed the thing before:
COUNT(id) | newusers | date
3 | 1 | 2016-12-15
3 | 0 | 2016-12-14
3 | 0 | 2016-12-13
3 | 0 | 2016-12-12
Sorry if I didn't explain this clear enough.
To get new users you want the first day an id appeared:
select id, min(date)
from t
group by id;
The rest is just a join and group by:
select d.date, cnt, count(dd.id) as newusers
from (select date, count(*) as cnt
from t
group by date
) d left join
(select id, min(date) as mindate
from t
group by id
) dd
on d.date = dd.mindate
group by d.date, d.cnt
limit 8;
To get the number of new users you need to compare them to a set of ids over the past 8 days
My MySQL is a bit rusty, so you might have to correct the syntax.
SELECT COUNT(id)
FROM table
WHERE id NOT IN (
SELECT DISTINCT id
FROM table
WHERE date BETWEEN DATE(DATE_SUB(NOW(), INTERVAL 8 DAY)) AND DATE(DATE_SUB(NOW(), INTERVAL 1 DAY))
)
I'll leave it as a task for you to combine it with your other query ;)
Hi if your date column in database is datetime/date or other date representing format you can do something like this:
for getting all users who accessed something in 8 days:
Select id, date from table
where date BETWEEN DATE_ADD(NOW(), INTERVAL -9 DAY) AND NOW()
I think, you can do whatever grouping you want on that.
To get new users, you can either go with self join or with sub select
selfjoin:
select t.id, t.date from table as t
LEFT join table as t2
ON t.id = t2.id
AND t.date BETWEEN DATE_ADD(NOW(), INTERVAL -1 DAY) AND NOW()
AND t2.date NOT BETWEEN DATE_ADD(NOW(), INTERVAL -9 DAY) AND NOW()
WHERE t2.id IS NULL
i used left join to match all access from users and then in where excluded those rows. However self joins are slow, and even slower with LEFT join
subselect:
select id, date from table
where date BETWEEN DATE_ADD(NOW(), INTERVAL -1 DAY) AND NOW()
AND id NOT IN (
SELECT id FROM table
WHERE date BETWEEN DATE_ADD(NOW(), INTERVAL -2 DAY) AND DATE_ADD(NOW(), INTERVAL -1 DAY)
)
I know those betweens with date_adds are not exactly nice looking, but i hope it will help you more than grouping dates
I would suggest using date with time for more information, but its entirely up to meaning of yours data
I have a table to register users logs every one minute and other activities using DateTime for each user_id
This is a sample data of my table
id | user_id | log_datetime
------------------------------------------
1 | 1 | 2016-09-25 13:01:08
2 | 1 | 2016-09-25 13:04:08
3 | 1 | 2016-09-25 13:07:08
4 | 1 | 2016-09-25 13:10:08
5 | 2 | 2016-09-25 13:11:08
6 | 1 | 2016-09-25 13:13:08
7 | 2 | 2016-09-25 13:13:09
8 | 2 | 2016-09-25 13:14:10
I would like to calculate the total active time on the system
UPDATE: Expected Output
For Example user_id 1 his total available time should be 00:12:00
Since his hours and seconds are same so I'll just subtract last log from previous then previous from next previous and so on then I'll sum all subtracted values
this a simple for
Simply I want to loop through the data from last record to first record with in my range
this is a simple formula I hope that make my question clear
SUM((T< n > - T< n-1 >) + (T< n-1 > - T< n-2 >) ... + (T< n-x > - T< n-first >))
Since user_id 1 his hours and seconds are the same then I'll calculate the minutes only.
(13-10)+(10-7)+(7-4)+(4-1) = 12
user_id | total_hours
---------------------------------
1 | 00:12:00
2 | 00:03:02
I did this code
SET #start_date = '2016-09-25';
SET #start_time = '13:00:00';
SET #end_date = '2016-09-25';
SET #end_time = '13:15:00';
SELECT
`ul1`.`user_id`, SEC_TO_TIME(SUM(TIME_TO_SEC(`dl1`.`log_datetime`))) AS total_hours
FROM
`users_logs` AS `ul1`
JOIN `users_logs` AS `ul2`
ON `ul1`.`id` = `ul2`.`id`
WHERE
`ul1`.`log_datetime` >= CONCAT(#start_date, ' ', #start_time)
AND
`ul2`.`log_datetime` <= CONCAT(#end_date, ' ', #end_time)
GROUP BY `ul1`.`user_id`
But this code Sum all Time not getting the difference. This is the output of the code
user_id | total_hours
---------------------------------
1 | 65:35:40
2 | 39:38:25
How can I calculate the Sum of all difference datetime, then I want to display his active hours every 12 hours (00:00:00 - 11:59:59) and (12:00:00 - 23:59:59) with in selected DateTime Period at the beginning of the code
So the output would look like this (just an dummy example not from given data)
user_id | total_hours | 00_12_am | 12_00_pm |
-------------------------------------------------------
1 | 10:10:40 | 02:05:20 | 08:05:20 |
2 | 04:10:20 | 01:05:10 | 03:05:30 |
Thank you
So you log every minute and if a user is available there is a log entry.
Then count the logs per user, so you have the number of total minutes.
select user_id, count(*) as total_minutes
from user_logs
group by user_id;
If you want them displayed as time use sec_to_time:
select user_id, sec_to_time(count(*) * 60) as total_hours
from user_logs
group by user_id;
As to conditional aggregation:
select
user_id,
count(*) as total_minutes,
count(case when hour(log_datetime) < 12 then 1 end) as total_minutes_am,
count(case when hour(log_datetime) >= 12 then 1 end) as total_minutes_pm
from user_logs
group by user_id;
UPDATE: In order to count each minute just once count distinct minutes, i.e. DATE_FORMAT(log_datetime, '%Y-%m-%d %H:%i'). This can be done with COUNT(DISTINCT ...) or with a subquery getting distinct values.
The complete query:
select
user_id,
count(*) as total_minutes,
count(case when log_hour < 12 then 1 end) as total_minutes_am,
count(case when log_hour >= 12 then 1 end) as total_minutes_pm
from
(
select distinct
user_id,
date_format(log_datetime, '%y-%m-%d %h:%i') as log_moment,
hour(log_datetime) as log_hour
from.user_logs
) log
group by user_id;
This is what I want:
Look if the highest created from the same FK is more than X days old.
This is how the data is structured (this is not the result from the query below):
table_1
id | FK_table_2 | created
-------------------------------------------------------
1 | 20 | 2013-11-12 12:13:14
2 | 20 | 2013-11-12 11:10:12
3 | 21 | 2013-10-02 12:53:20
4 | 21 | 2013-09-02 12:54:20
Note: Doing a subquery will be to slow.
What I come up with is:
SELECT *
FROM table_1
GROUP BY FK_table_2
HAVING MAX(created) < NOW() - INTERVAL 3 DAY
I'm worried that HAVING MAX(created) has not garantuee to use the highest created.
Is there any other ways to do this?
I don't think you need to use a MAX clause, you can surely just select all rows older than 3 days and do your work on them.
SELECT DISTINCT FK_table_2 FROM table_1
WHERE created > NOW() - INTERVAL 3 DAY;
Update this won't work :-(
try this
SELECT FK_table_2,max(created)
FROM table_1
where created < NOW() - INTERVAL 3 DAY
GROUP BY FK_table_2