group a set of rows between 2 varchar values - mysql

I have the following MySQL table
1 id mediumint(9)
2 user_id mediumint(9)
3 location_id mediumint(9)
4 timestamp timestamp
5 activity varchar(100)
6 points mediumint(9)
I want to query user_id, location_id, date, SUM(points) between (grouped by) 2 different activities (checkin and checkout), but i can't figure out how.
Any activity between checkin and checkout should be allowed.
1 38 13 2015-05-13 13:26:01 checkin 100
2 38 13 2015-05-13 13:26:07 add_points 5
3 38 13 2015-05-13 13:26:13 add_points 5
4 38 13 2015-05-13 13:26:19 add_points 5
5 38 13 2015-05-13 13:26:26 add_points 5
6 38 13 2015-05-13 13:26:31 add_points 5
7 38 13 2015-05-13 13:26:37 add_points 5
8 38 13 2015-05-13 13:33:42 checkout 0
the result for this set should be:
userid location date sum of points between checkin and checkout
38 13 2015-05-13 130
when there are more checkin and checkouts, the result should add another row.

http://sqlfiddle.com/#!9/ba90b/2
SELECT t.*,
SUM(t.points)
FROM (
SELECT *,
IF(activity='checkin', #gr:=CONCAT(user_id,`timestamp`), #gr) gr,
IF(activity='checkout', #gr:=null, #gr)
FROM table1
ORDER BY user_id,`timestamp`) t
GROUP BY t.gr

I guess this would do, because your also summarizing the points from checkin (100) and checkout (0).
I assumed that userid and location are a unique combination else you have to work with date indeed.
SELECT userid
, location
, DATE_FORMAT(date,'%m-%d-%Y')
, sum(points) total_points
FROM table
GROUP BY userid
, location
, DATE_FORMAT(date,'%m-%d-%Y');
If there are multiple checkin / checkouts with the same userid and location then you can consider to add a column like session to your table or an other unique identifier. It makes it more easier to query. You can use that identifier in your GROUP BY to get the multiple records you would like to have.

Related

How to rank by counting data in multiple rows in a column with certain conditions on it in MySQL

I Have a table something like below
edit 1 column id is the primary key
id ref_id count_value
10 34 5
11 34 2
12 36 3
13 30 1
14 25 20
15 34 15
15 36 10
what I want is to align and fetch the data in such a manner where
the value in count_value field will be add up for each corresponding ref_id
so here in the example
ref_id 34 have three entries and total count_value of 22
ref_id 36 have two entries and total count_value of 13
ref_id 25 have one entry and total count_value of 20
so that I am expecting is to be in this manner
ref_id
34
25
36
30
I tried using group by but that isn't going to solve this I guess as I want to add up the value present inside cell and then rank it up according to the final count
regarding the condition part in the question there is a timestamp column and will need to get only that data which is created after certain datetime
You can group by ref_id, and then order the records by descending sum() of count_value:
select ref_id
from mytable
group by ref_id
order by sum(count_value) desc
You can add a where clause to the query to implement the filter on the timestamp column (which you did not show in your sample data): it goes between the from clause and the group by clause.
Demo on DB Fiddle:
| ref_id |
| -----: |
| 34 |
| 25 |
| 36 |
| 30 |

SQL joining on two columns with a variation on the first column

I have two tables:
Table 1: planA
ID Date Count
3 2017-01-01 10
2 2017-02-03 15
10 2017-01-30 8
Table 2: planB
ID Date Value
3 2017-01-02 11
2 2017-02-04 12
21 2017-01-30 3
3 2017-02-03 33
What I want to do is to join the two tables on (ID and Date) columns.
However, on Date, I want to use the next day to the date on the table 1.
Therefore, the joined table should look like the following:
PlanA.ID PlanA.Date PlanB.Date PlanA.Count PlanB.Value
3 2017-01-01 2017-01-02 10 11
2 2017-02-03 2017-02-04 15 12
Is this even possible?
Any suggestion would be appreciated!
Yes it is possible:
select
PlanA.ID,
PlanA.Date,
PlanB.Date,
PlanA.Count,
PlanB.Value
from
PlanA inner join PlanB
on (
PlanA.ID = PlanB.ID
and
PlanA.Date + INTERVAL 1 DAY = PlanB.Date
)
if Date is a column of type date, + INTERVAL 1 DAY will return the next day of the one given, and then you can perform the join.

SQL count rows where id = x and other max(id) grouped on the same table

I need to count rows in one table where the field event_id = 17 and their isn't any other record in the table with higher g_event_id and the same value for prim_cid. My table contains events for phone calls. All events for the same call share the field "prim_cid". If the field event_id = 17 i know that the call is in queuee , but as soon its answered an new entry in table (same prim_cid) but other event_id occur. So i need to count the rows with event_id = 17 with has no later record with same prim_cid.
My table:
events:
g_event_id prim_cid event_id event_time
---------- -------- -------- ----------
1 1 16 2016-10-21 16:00:00
2 1 17 2016-10-21 16:00:01
3 1 18 2016-10-21 16:00:02
4 2 15 2016-10-21 16:01:01
5 2 17 2016-10-21 16:01:02
6 3 16 2016-10-21 16:02:01
7 3 17 2016-10-21 16:02:02
8 3 18 2016-10-21 16:02:38
From this i like to get the result:
1
(as only prim_cid 2 has no higher record on the field g_event_id)
Also i would like to do an select where i get the record like:
g_event_id prim_cid event_id event_time
---------- -------- -------- ----------
5 2 17 2016-10-21 16:01:02
In another sql select of course :)
You want to count prim_cids who "know" an event_id 17 but have no other g_event_id that is higher, than that of the 17-event. This translates directly into SQL:
SELECT COUNT(DISTINCT seventeens.`prim_cid`)
FROM `events` AS seventeens
LEFT JOIN `events` AS laters ON (seventeens.`prim_cid` = laters.`prim_cid` AND laters.`g_event_id` > seventeens.`g_event_id`)
WHERE seventeens.`event_id` = 17
AND ISNULL(laters.`prim_cid`)
In order to fulfill your second statement you would use the following SELECT clause for the same statement:
SELECT DISTINCT seventeens.*
FROM ...
here you go :)
SELECT COUNT(ev1.prim_cid)
FROM events ev1
WHERE ev1.event_id = 17
AND (SELECT prim_cid
FROM events
WHERE g_event_id > ev1.g_event_id
AND prim_cid = ev1.prim_cid) IS NULL;

Getting result for latest row(based on timestamp column) for each user and each day

I have a table called play_progress.
play_progress
id user_id coins timecreated
1 1 20 2016-01-23 06:55:09
2 1 24 2016-01-23 06:59:22
3 1 28 2016-01-23 07:05:34
4 2 4 2016-01-23 07:10:58
5 2 10 2016-01-23 07:12:08
6 1 32 2016-01-24 00:07:48
7 2 14 2016-01-24 00:12:08
8 1 35 2016-01-24 00:44:48
9 2 18 2016-01-24 00:55:08
I like to get the latest row( based on timecreated) for each day for each user.
I have tried the following query;
SELECT user_id, coins, MAX(timecreated)
FROM player_progress
GROUP BY user_id, DATE(timecreated);
It gives the result for each day but it gives wrong timecreatd value.
Where I am going wrong?
Result details like
id user_id coins timecreated
1 1 28 2016-01-23 07:05:34
5 2 10 2016-01-23 07:12:08
8 1 35 2016-01-24 00:44:48
9 2 18 2016-01-24 00:55:08
I have searched through SO, but couldn't find a solution to my problem.
If you need to fetch more columns then the ones used for grouping (user_id and timecreatd) you need a more complex query:
SELECT p.user_id, p.id, coins, p.timecreated
FROM play_progress p INNER JOIN
(SELECT user_id, MAX(timecreated) as max_time
FROM play_progress
GROUP BY user_id, DATE(timecreated)) pp
ON p.user_id = pp.user_id
AND p.timecreated = pp.max_time;
Here you have a sample

Improve sql query in MySQL in PHPMYADMIN

I have this query:
SELECT `jos_eb_registrants`. * , `jos_eb_field_values`. *
FROM jos_eb_registrants, jos_eb_field_values
WHERE `jos_eb_registrants`.`event_id` =3
AND `jos_eb_registrants`.`id` = `jos_eb_field_values`.`registrant_id`
It returns me everything from these two tables, but gives me rows with duplicate names, because ONE name from first table can have more than one field value. How to make field values not in separate rows, but in one row near one name, without duplicates. Please edit this query with my variables.Tables connected via Id and registrant_id.
jos_eb_field_values
1 id
2 registrant_id
3 field_id
4 field_value
jos_eb_registrants
1 id
2 event_id
3 user_id
4 group_id
5 first_name
6 last_name
7 organization
8 address
9 address2
10 city
11 state
12 country
13 zip
14 phone
15 fax
16 email
17 number_registrants
18 total_amount
19 discount_amount
20 amount
21 register_date
22 payment_date
23 payment_method
24 transaction_id
25 comment text
26 published
27 cart_id int(11)
28 deposit_amount
29 payment_status
30 coupon_id
31 check_coupon
32 tax_amount
33 registration_code
34 is_reminder_sent
35 is_group_billing
Try this:
SELECT DISTINCT jos_eb_registrants. * , jos_eb_field_values. *
FROM jos_eb_registrants
INNER JOIN jos_eb_field_values ON jos_eb_registrants.id = jos_eb_field_values.registrant_id
WHERE jos_eb_registrants.event_id =3