Get last value in multiple rows MYSQL - mysql

I have a table that I use to record the activity log of an application. Now I have to get all records from entity X that have been published in some range of dates. So if a record has been published and later unpublished, it doesn't have to appear in the results.
I don't know how to explain it really, it's find the last appearance of each one and then catch values that are "1" or "0", on depends that I need in each case.
A simplified example (the real table has more fields and more data):
id user_id date model main_relation_id field new_value
1 24 2017-03-21 A 1 publish 1
2 24 2017-03-21 A 2 publish 1
3 24 2017-03-22 A 3 publish 0
4 24 2017-03-22 A 2 update some text
5 24 2017-03-23 A 1 publish 0
6 24 2017-03-23 A 1 update some text
7 24 2017-03-24 A 3 publish 1
8 24 2017-03-24 A 2 publish 0
9 24 2017-03-24 A 2 update some text
10 24 2017-03-25 A 1 publish 1
11 24 2017-03-25 A 2 publish 1
11 24 2017-03-26 A 3 publish 0
I need to get main_relation_id, filtering by model and date, so if I want to get all registers from model A that have been published between 2017-03-21 and 2017-03-24 I'll get:
model_main_relation_id
1
3
and if I want to get all registers that have been unpublished in the same dates, the result have to be:
model_main_relation_id
2
How can I get this result?

So, you would like to filter on the latest status by main_relation_id, whether the particular main_relation_id has been published (field='publish'; new_value=1) or unpublished (field='publish'; new_value=0) within a period.
Since the dates within the date field of the sample data are equal for multiple records, therefore I must assume that a higher value in the id field means later event. Therefore the max(id) per main_relation_id would yield the latest even record.
What I would do is to get the max(id) per main_relation_id within a date range for a particular model in a derived table where field is 'publish' and join this back to your table to find out whether the particular main_relation_id was published:
select table.main_relation_id
from table
inner join
(select main_relation_id, max(id) as maxid
from table
where date>=... and date<=... and `field`='publish' and model='...'
group by main_relation_id) t on table.id=t.maxid
where table.new_value=1
You need to substitute the filter criteria in place of the .... If you would like to get the unpublished data, then replace table.new_value=1 criterion with table.new_value=0.

Related

Mysql get user list of every week interval

I want to write query to fetch user from table who register before week interval.
For ex. todays date is 2017-08-17, then I need user who register on 2017-08-10, 2017-08-03,2017-07-27 and so on. Like this if todays date is 2017-08-20 then user will be register on 2017-08-13, 2017-08-06.
id name date
1 ABC 2018-08-16
2 PQR 2018-08-10
3 LMN 2018-07-27
4 AAA 2018-01-01
Output will be
id name date
2 PQR 2018-08-10
3 LMN 2018-07-27
One way to express this problem is to recognize that we want to retain dates whose difference from today are multiple of 7 days. We can compare the UNIX timestamps of each record and check to see if the number of seconds, when divided by the number of seconds in 7 days, is zero.
SELECT *
FROM yourTable
WHERE
MOD(UNIX_TIMESTAMP(CURDATE()) -
UNIX_TIMESTAMP(DATE(reg_date)), 7*24*60*60) = 0
Demo here:
Rextester
SELECT * FROM user WHERE WEEKDAY(`date`) = WEEKDAY(NOW());
This will get you all users that registered 0, 7, 14, 21 etc. days ago.

Sort values in two column and insert order position into another column in mysql

I have a database about sports event that contains:
*User ID
*Amount of Points that the user got on that event
*Time (HH:MM:SS) that took the user to complete track.
How can I first sort them by no. of points, then if two users have same amount of points, by time (shorter is better); and then insert the places to rows?
I have database like that:
ID No. of Points Time Place
------------------------------------
1 15 00:56:00
2 13 00:55:15
3 17 01:00:00
4 17 00:57:00
5 19 00:52:15
I need to have it with places:
ID No. of Points Time Place
------------------------------------
1 15 00:56:00 4
2 13 00:55:15 5
3 17 01:00:00 3
4 17 00:57:00 2
5 19 00:52:15 1
I hope, you understand that. Sorry for bad English.
Best regards,
You can do this with update statement as follows.
SET #placeValue:=0;
UPDATE [Table Name] SET Place=#placeValue:=#placeValue+1 ORDER BY
[Amount of Points] DESC,Time ASC

Count the number of rows that have a specific piece of data?

I have the following table
id Desc User
1 Print 14
2 Print 7
3 Copy 14
4 Print 19
5 Copy 7
6 Copy 19
7 Attach 19
What I'm trying to do is make a column that tells the number of rows per user.
Like this
id User Count
1 14 2
2 7 2
4 19 3
The Point of the report is to show how many activities each user has done.
I need to group by user and get the number of rows within each user.
The problem is, I'm not exactly sure how to do that, is it a unique statement somewhere?
Here's my query so far.
Select id
,User
From Table
Group By User
I am unsure how to implement the count though.
You should be able to get your result with the COUNT function:
SELECT
MIN(id),
User,
COUNT(User) AS Count
FROM
`table`
GROUP BY
User
Because you can get only one id value per User I assumed from your data that you want the minimum one.

MySQL GROUP BY with multiple parameters hiding zeros

I've read similar questions here on stackoverflow, but the OP's table structure is never quite the same as mine, so the answer doesn't work for me. The posts I've read are only trying to GROUP BY one column as opposed to two. I'm using MySQL, latest stable release.
Here's my table "reference":
id formatID referenceTime
1 1 2011-6-12 12:40
2 2 2011-6-12 1:04
3 4 2011-6-12 1:03
4 2 2011-6-12 15:20
5 3 2011-6-12 9:30
6 3 2011-6-12 2:55
7 5 2011-6-12 13:15
8 1 2011-6-12 12:32
(etc)
I want to create a query that show how many of each type of format occurred by hour of day. The point of this is to see what is the busiest time of day. I am trying to write a query that will create output that I can use for some simple graph web apps (Highcharts.js). I want it to look like this:
Timeofday Subgroup Count
12AM 1 2
12AM 2 6
12AM 3 7
12AM 4 2
12AM 5 0
1AM 1 3
1AM 2 3
1AM 3 0
1AM 4 0
1AM 5 1
(etc)
I'm using this query:
SELECT date_format(referenceTime,'%I %p') AS timeofday,
reference.referenceFormatID AS subgroup,
count(*) AS count
FROM reference
GROUP BY timeofday,subgroup ASC
However, the output skips "rows" where the count equals zero and so ends up looking like this:
Timeofday Subgroup Count
12AM 1 2
12AM 2 6
1AM 3 7
1AM 4 2
1AM 5 1
3AM 1 3
6AM 2 3
7AM 3 1
7AM 4 1
9AM 5 1
(etc)
I need those zeros to be able to create a properly formatted data series for my app.
The LEFT JOIN method where you put all the times into a second table isn't working for me because I am grouping by two different columns. Apparently, the LEFT JOIN criteria is satisfied as long as each hour shows up somewhere in the output table, but I need each hour to appear for each format.
Any suggestions?
You have two options, either create a lookup table with the possible hours in it, or use strange query involving the dual table and union to get the values that you are looking for.
In the first case, you would have a table with maybe a single field for the moment, let's just call it hours and the field is timeofday.
In the hours timeofday, you would have the following data:
timeofday
12AM
1AM
2AM
....
Then your query is as simple as
SELECT hours.timeofday,
reference.referenceFormatID AS subgroup,
count(reference.referenceFormatID) AS count
FROM hours
LEFT JOIN reference on date_format(referenceTime,'%I %p') = hours.timeofday
GROUP BY hours.timeofday,subgroup ASC
EDIT
To get all combinations, you would also need a formats table with all the possible formatIDs as was mentioned by rfausak. You could also do this with a distinct, but let's just assume that you have this table, let's call it formats. Again, this table could have a single column.
Part 1 is to get all the combinations:
SELECT hours.timeofday,
formats.ID
from hours
join formats
This is a Cartesian join that would merge all possible hours and format IDs.
Now we add in the LEFT JOIN
SELECT hours.timeofday,
formats.ID,
count(reference.subgroup)
FROM hours
JOIN formats
LEFT JOIN reference on date_format(referenceTime,'%I %p') = hours.timeofday
AND reference.subgroup = formats.ID
GROUP BY hours.timeofday,formats.ID ASC
If you try to do it using a DUAL table look up, you can use a method similar to generate days from date range

MySQL Select: Get Main Record(s) by Multiple Attached Records?

Not sure how to ask this so it makes sense, but I'm trying to do a query like:
SELECT * FROM PAGES WHERE an attached record exists in PAGE_FILTERS and that record has a FilterTypeID of 22 AND another attached record exists in PAGE_FILTERS for the same page ID and that record has a filter type id of 27.
I have a structure like this:
PAGES table
PageID PageName
1 Page 1
2 Page 2
3 Page 3
PAGE_FILTERS table
PageID FilterTypeID FilterValueID
1 22 1
1 27 2
2 22 0
2 24 1
3 22 1
3 27 1
3 28 2
So, given FilterTypeID's of 22 and 27, my query should return PageID's 1 and 3. Page 2 doesn't get selected since 22 matches, but there's no record matching FilterTypeID 27.
Page 3 matches, even though there's an extra filter.
In other words, I know what filter types a page has to have, and I need to get all the pages that each have all the required types.
I'm not opposed to changing database structure if it makes more sense, but each page could have none, one, or many filter sets attached.
SELECT p.*
FROM pages p
JOIN PAGE_FILTERS pf
ON p.PageID = pf.PageID
AND pf.FilterTypeID IN (22,27)
GROUP BY p.PageID
HAVING COUNT(DISTINCT pf.FilterTypeID) = 2