Limiting SQL Query by most recent rows within larger query - php

I'm generally pretty self reliant on fudging something together that works but I have run into a brick wall on this one and am eventually reaching out for a nod in teh right direction..
my query:
$post_views = (int)$wpdb->get_var("
SELECT SUM(count) AS views
FROM ".$wpdb->prefix."post_views
WHERE id IN (".$post_id.") AND type = 0"
The database table looks like this :
id type period count
------- ------- ----------- -------
32310 0 20141023 8
32310 0 20141022 68
32310 1 201443 76
32310 2 201410 76
32310 3 2014 76
32310 4 total 76
The type 0 are the ones I'm interested in, I just want the sum of the COUNT column for the most recent 7 type 0 entries
I have been trying with things based around "ORDER BY period DESC LIMIT 7 " on the end of the query - to no avail, I generally get returns of 0 doing this.
a new type 0 row will be generated for each article every day, so thats why I need to only get the last 7
any help here would be massively appreciated, totally stuck for the first time ever with this.

SELECT SUM(count)
FROM (SELECT count
FROM wp_post_views
WHERE type = 0
AND id IN (684,42,7)
ORDER BY period DESC
LIMIT 7)
Or just determine the date a week ago first and use that to filter, but a subquery like this will work fine as well.

Related

Get next and previous records sorting by non-unique field

I was not able to find an answer while reading similar questions, so I'll ask my question here, appreciate any help on this matter.
In MySQL DB have a table with articles:
id date is_active title text
3 2017-01-20 1 New payment system goes live some articl
5 2017-01-21 1 Library v.2.5 released some articl
6 2017-01-22 1 New skins and themes some articl
7 2017-01-25 0 Terms and Conditions updated some articl
8 2017-01-26 1 Don't forget to subscribe some articl
10 2017-01-22 0 Support Chat beta release some articl
11 2017-01-30 1 Maintenance window next Sunday some articl
12 2017-01-28 1 Refer a friend and get a bonus some articl
13 2017-01-26 1 Follow us in social networks some articl
14 2017-01-22 1 Video sharing feature is now live some articl
I have 2 web pages:
a list of all active articles ordered by date (important: it is possible that several articles can have same date).
This works fine, no issue here.
single article read page, additionally I have "Next" and "Previous" links on that page
This is an issue.
I would like to show 'next' and 'prev' links as a href="article.php?id=8". So I would like to get next record ID from DB according to the query like this:
SELECT id FROM articles WHERE date > (SELECT date FROM news WHERE id = 6) and isactive = 1 ORDER BY date ASC LIMIT 1;
However my query does not work properly when it comes to defining next article id with the same date. When user stays on the article id=3 and clicks 'next' multiple times I would expect the following order of loading articles:
id title date is_active
5 Library v.2 2017-01-21 1
6 New skins a 2017-01-22 1
14 Video shari 2017-01-22 1
8 Don't forge 2017-01-26 1
13 Follow us i 2017-01-26 1
12 Refer a fri 2017-01-28 1
11 Maintenance 2017-01-30 1
But what I get is: 5, 6, 8, 12, 11. So 2 records are missing in this sequence (ids: 14 and 13) because they have same date.
I tried playing with different queries, but all results are not 100% right (in some cases it keeps returning same numbers, ex.: 5, 6, 14, 6, 14....., etc. )
Is is possible to get the 'next' IDs based on current ID and desired order via MySQL query(ies)? I am not against doing several queries or working with nested queries.
As a workaround, of course I can just retrieve an ordered array of all ids like this:
SELECT id FROM articles WHERE isactive=1 ORDER BY date
and then define 'next' and 'previous' using this array, however I don't like this solution.
If you can point me to some similar topics or other possible ways to solve this, please do.
Thank you.
SELECT id
FROM articles
WHERE date >= (SELECT date -- changed
FROM news
WHERE id = 6)
AND isactive = 1
AND id NOT IN(6) -- added, maybe id!=6 or id<>6
ORDER BY date ASC
LIMIT 1
-- (all id date >= date) - (id=6)
Why you do this, why not use
SELECT id FROM news ORDER BY date ASC LIMIT 6,1 -- possition, count
If SQL query caching, this is may be faster.

Sum user working time in a given MySQL table

The following table has the time when the user enters/quit on the company:
ID | user_id | day_unix | time
10 1 1459220400 1459293745
9 1 1459220400 1459293711
8 1 1459220400 1459293689
7 1 1459220400 1459293678
6 1 1459220400 1459293669
11 1 1459220400 1459293761
day_unix consists in the first second of the day, this way, GROUP BY can be easily used in future.
time consists in the time that the user click's on the button to start/stop working. Time also can be changed to a native DATETIME column.
I want to create a SQL query capable of summing the time between the entries. So the query must to jump "odd" entries that can be considered as the beginnig of a small coffee break and right after the "odd" entries the user has started working again, so the query must to sum the working time, excluding the coffee breaks.
Any idea? Here is what I've already got:
SELECT * FROM table GROUP BY day_unix ORDER BY time ASC

PHP MySQL remove quantity

i met with situation when need to import values with quantity that will be spended many times by some qty.
Eg. i have table with product material
ID TYPE QUANTITY SPENT
1 1 10 0
2 1 100 0
Now i spent 20 qty of material ONCE and need to update field SPENT to be like this
ID TYPE QUANTITY SPENT
1 1 10 10 <--- 0 left
2 1 100 10 <--- 90 left
Or i spend 8 qty first then another 20 qty, so table needs to be like this
First - spent 8
ID TYPE QUANTITY SPENT
1 1 10 8 <--- 2 left
2 1 100 0 <--- 100 left
Second - spent 20
ID TYPE QUANTITY SPENT
1 1 10 10 <--- 0 left
2 1 100 18 <--- 72 left
So i need to separate spended material quantity by avaible and reduce till limit then reduce other one with avaible qty.
What is the best way for this with php?
Please any help will be appreciated, thank you!
UPDATE `tablename` SET `SPENT` = 10, `QUANTITY` = `QUANTITY` - `SPENT` WHERE `ID` = 1
Note that the ID and SPENT fields fields have example values (10 and 1 can be changed, depends on you)
UPDATE tablename SET SPENT = your_variable, QUANTITY = QUANTITY - your_variable WHERE ID = your_row_id
I would do this something like this (REQUESTED is number of items requested):
Start database transaction (to prevent changing spent values by other processes)
Select one or more rows (you can select all rows if you know there wont be a lot of them. also select only those where QUANTITY > SPENT).
In PHP start adding SPENT and reduce REQUESTED row by row (if you didn't get all rows previously you need to get new rows as they are needed).
If REQUESTED is 0 it means you can save all rows do DB and commit transaction, else if REQUESTED > 0 and there no more rows where QUANTITY > SPENT then rollback transaction and inform user that he requested more than its available.

Need to pull data from mysql by unique userid, max rounds, then sort by another value

A couple months ago I asked a question about something similiar to this, received some help and thought I had the answer. 3 months later I am seeing this didnt work 100% so I need some more help but I can ask the question better now that I understand more.
I have a mysql table with id, userid, rounds, reps, exerciseid
I need to pull a users highest round specific to the exercise I am pulling for. So if the exerciseid was 8 I would need the users top round for that exerciseid but if the user has the same rounds more than once, which happens a lot, then I need to sort that by the reps to give me a true highest performance. Now, after obtaining those results I need to then sort this data set by rounds,reps so if multiple unique users have the same rounds that is then ordered by reps.
Can this be done with pure mysql or am I better off pulling the data and sorting everything with PHP?
SELECT
max(l.rounds) as rounds,
l.reps,l.userid
from leaderboard l
where l.exerciseid = 8
group by l.userid
order by
rounds desc,
reps desc
example of structure
First this is a smaple set
userid exerciseid rounds reps
-- -- --
1 8 23 10
1 8 23 15
1 8 20 10
2 8 28 19
2 8 15 12
3 8 40 29
results I want
userid exerciseid rounds reps
-- -- --
3 8 40 29
2 8 28 19
1 8 23 15
If I understand this correctly, you want to first group by userid and rounds to get the maxreps on a round. Then you want to select the max rounds from this.
Here is one way to express this in MySQL:
select userid, rounds, maxreps
from (SELECT userid, l.rounds, MAX(l.reps) as maxreps
from leaderboard l
where l.exerciseid = 8
group by l.userid, l.rounds
) ur
where exists (select 1 from leaderboard lb where ur.userid = lb.userid and lb.exerciseid = 8 group by lb.userid having max(rounds) = ur.rounds))
order by rounds desc, maxreps desc
how about:
SELECT
max(l.rounds) as rounds,
max(l.reps) as reps,l.userid
from leaderboard l
where l.exerciseid = 8
group by l.userid, l.exerciseid
order by
rounds desc,
reps desc

Count number of occurences of a value in different columns in *one* row/record

I might be doing this the wrong way when I set up the tables?
I'm using mysql & php. Loads of googleing only shows how to count how many times a value appears in several rows, I want check for a value in many different columns but in the same record. (I think this: count number of columns that have data for each row just might be about the same thing, maybe? but I don't get it.)
I have a table with goals that I hope to work on and achieve every day. So for every day I wish to mark: "success" or "fail". And insert is working great. How ever I'm looking for a way to calculate the number of success& number of fails of "today", to show the right kind of smiley which will be encouraging or sad depending on number of fails and number of successes.
For example:
ID date drinkMoreWater goToBedEarlier callADearFriend
1 2012 jan 15 fail fail fail
1 2012 jan 16 success _(still empty) success
So if today is jan 15 the smiley will be very very sad.
If today is jan 16 the smiley will be really really hppy with stars in it's eye's (atleast until I fail goal 2 ;) )
Your tables should actually be structured differently to make your life easier:
Goals:
ID Goal
1 drinkMoreWater
2 goToBedEarly
3 callADearFriend
Status:
ID Status
1 Success
2 Fail
Tracking:
ID Date Goal_ID Status_ID
1 1/1/2012 1 1
1 1/1/2012 3 2
1 1/2/2012 2 1
1 1/2/2012 4 1
Now you could easily add goals and status (e.g. 'Working on it') and your table structure does not have to change to accommodate your changes, your queries become a lot simpler as well.
If you want to do that in SQL, you could use a ternary-like construct, like that:
SELECT *,
(CASE drinkMoreWater WHEN 'success' THEN 1 ELSE 0 END)
+ (CASE goToBedEarlier WHEN 'success' THEN 1 ELSE 0 END)
+ (CASE callADearFriend WHEN 'success' THEN 1 ELSE 0 END)
AS numberOfSuccesses
FROM yourTable
You can do something like this:
Select case when sub.smilies = 0 then "very very sad" else
case when sub.smilies = 1 then "sad" else "hubby" end
end as "Number of Smilies"
from
(
Select case when t.drinkMoreWater = "fail" then 0 else 1 end +
case when t.goToBedEarlier = "fail" then 0 else 1 end +
case when t.callADearFriend = "fail" then 0 else 1 end as smilies
from yourTableName t
where date = #date
) sub
You will need to handle the empty strings, and work around these case statements.
This solution is for your current design but you better off consider the redesign suggested by #BassamMehanni 's answer

Categories