If column is greater than "int", appear more than once - mysql

I've got a table which contains week numbers and id's
| id | week |
| 1 | 1 |
| 2 | 2 |
| 3 | 6 |
| 4 | 8 |
What I need to do is retrieve based on the value of week. But I also need to return the row more than once if the row is greater than a certain number.
For instance (pseudo),
if week > 2
and week > 6
| id | week |
| 2 | 2 |
| 3 | 6 |
| 3 | 6 |
| 4 | 8 |
| 4 | 8 |
ID 3 & ID 4 appear twice, because they're greater than both 2 and 6. ID 2 will only appear once because it is only greater than 2.
Unfortunately looped queries are sort of out of the question as this query will be return 2k+ rows.
Any help will be greatly appreciated, even if the solution is PHP based.

Split the query into multiple queries and then merge the result using UNION.
The following should give you the result you want.
(SELECT * FROM yourTable WHERE week > 2)
UNION ALL
(SELECT * FROM yourTable WHERE week > 6)
edited included the hint by Lily - thx.

Related

How can I get the last row of every stage of every job? [duplicate]

This question already has an answer here:
Mysql group by two columns and pick the maximum value of third column
(1 answer)
Closed 2 years ago.
I've been taking too long trying to solve this, I need to filter this table:
+----+-------+-------+
| id | jobID |stageID|
+----+-------+-------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 2 |
| 4 | 1 | 1 |
| 5 | 2 | 2 |
| 6 | 2 | 1 |
| 7 | 2 | 1 |
| 8 | 2 | 2 |
+----+-------+-------+
You see every job has many rows with different stages, I need to get the last row of every stage of every job.
For example, look at job 1. It has 4 rows, each one with a given stage. I'd need to get the last entry of a stage for that job, which means, rows 3 and 4.
So for the full table I need to get rows No. 3, 4, 7 and 8, like this
+----+-------+-------+
| id | jobID |stageID|
+----+-------+-------+
| 3 | 1 | 2 |
| 4 | 1 | 1 |
| 7 | 2 | 1 |
| 8 | 2 | 2 |
+----+-------+-------+
I think I'll go nuts. I try with GROUP_BY but it groups the stages without taking in count the jobs.
Can you help me?
This is simply:
select max(id) as id, jobID, stageID
from yourtable
group by jobID, stageID
If you need additional information selected, use that as a subselect:
select yourtable.id, yourtable.jobID, yourtable.stageID, yourtable.other
from (
select max(id) as id
from yourtable
group by jobID, stageID
) max_job_stage_ids
join yourtable using (id)
or use IN (I find this less helpful in visualizing the query plan, but some people prefer it):
select id, jobID, stageID, other
from yourtable
where id in (select max(id) from yourtable group by jobID, stageID)

SQL calculate timediff between intervals including a time from a separate table

I have 2 different tables called observations and intervals.
observations:
id | type, | start
------------------------------------
1 | classroom | 2017-06-07 16:18:40
2 | classroom | 2017-06-01 15:12:00
intervals:
+----+----------------+--------+------+---------------------+
| id | observation_id | number | task | time |
+----+----------------+--------+------+---------------------+
| 1 | 1 | 1 | 1 | 07/06/2017 16:18:48 |
| 2 | 1 | 2 | 0 | 07/06/2017 16:18:55 |
| 3 | 1 | 3 | 1 | 07/06/2017 16:19:00 |
| 4 | 2 | 1 | 3 | 01/06/2017 15:12:10 |
| 5 | 2 | 2 | 1 | 01/06/2017 15:12:15 |
+----+----------------+--------+------+---------------------+
I want a view that will display:
observation_id | time_on_task (total time in seconds where task = 1)
1 | 13
2 | 5
So I must first check to see if the first observation has task = 1, if it is I must record the difference between the current interval and the start from the observations table, then add that to the total time. From there on after if the task = 1, I just add the time difference from the current interval and previous interval.
I know I can use:
select observation_id, TIME_TO_SEC(TIMEDIFF(max(time),min(time)))
from your_table
group by observation_id
to find the total time in the intervals table between all intervals outside of the first one.
But
1. I need to only include interval times where task = 1. (The endtime for the interval is the one listed)
2. Need the timediff between the first interval and initial start (from observations table) if number = 1
I'm still new to the Stackoverflow community, but you could try to use SQL
LAG() function
For instance
Using an outer Select Statement
SELECT COl1, COL2, (DATEDIFF(mi, Inner.prevtime, Currentdatetime,0)) AS Difference
FROM ( SELECT LAG(Created_Datetime) OVER (ORDER BY Created_Datetime) AS prevtime
From MyTable
Where SomeCondition) as Inner
Sorry if it looks goofy, still trying to learn to format code here.
https://explainextended.com/2009/03/12/analytic-functions-optimizing-lag-lead-first_value-last_value/
Hope it helps

Counting patterns from table mysql

I have the following data in a Mysql table
ID | code | code order
1 | 1 | 1
1 | 2 | 2
1 | 3 | 3
2 | 1 | 1
2 | 2 | 2
2 | 3 | 3
3 | 1 | 1
3 | 4 | 2
3 | 5 | 3
4 | 1 | 1
4 | 4 | 2
4 | 5 | 3
4 | 6 | 4
How would I write a query to return the following results
code pattern 1,2,3 = 2 (count)
code pattern 1,4,5 = 1 (count)
code pattern 1,4,5,6 = 1 (count)
basically I need to find out the most popular code sequence, each sequence is grouped by an unique ID. The order the codes of the is also important. i.e
1,4,5,6 is different to 1,5,4,6
cheers
In MySQL, this is probably most easily done using two aggregation:
select pattern, count(*)
from (select id, group_concat(code order by code) as pattern
from t
group by id
) p
group by pattern;

Order rows by other column value if value in different rows is same mysql [duplicate]

This question already has answers here:
SQL multiple column ordering
(9 answers)
Closed 8 years ago.
I've sorted a mySQL table by total. But it can happen that some rows have the same value. If the rows have the same value I want to sort them by another row. Is this possible?
ID | pos | name | m1 | m2 | total
1 | 1 | mike | 1 | 1 | 50
2 | 2 | alex | 16 | 12 | 14
3 | 3 | joe | 25 | 7 | 14
4 | 4 | jani | 7 | 24 | 14
The table is sorted by total, but if total is the same I want to sort the rows with the same value by the m2 column and change the pos by that order.
Yes, it's possible - you can give several columns in the order by clause:
SELECT *
FROM my_table
ORDER BY total DESC, m2 DESC

SQL query to find a winner depending on winning odds

I need a SQL query to determine a random winner. Each user has it's own winning odds. The more the winning_odds value is high, the more the user has chances to win. Here's a look at the table structure:
id email winning_odds
1 test#test.com 3
2 test2#test.com 5
3 test3#test.com 2
4 test4#test.com 1
5 test5#test.com 9
MySQL database. Table has approximately 100000 rows. There's only one winner, one time. Emails are unique. Anyone has a solution?
Thanks.
Select email from user order by winning_odds*rand() limit 1
I really liked this question, I'm posting the answer for postgresql.
select
*, generate_series(1, mytable.winning_odds)
from
mytable
order by
random()
limit 1;
This is how it works. For each row of your table, we replicate the row N times as your winning odds.
So you get at first and without limiting the query results:
5 | test5#test.com | 9 | 9
2 | test2#test.com | 5 | 3
3 | test3#test.com | 2 | 1
1 | test#test.com | 3 | 1
5 | test5#test.com | 9 | 5
1 | test#test.com | 3 | 3
5 | test5#test.com | 9 | 2
2 | test2#test.com | 5 | 4
2 | test2#test.com | 5 | 5
5 | test5#test.com | 9 | 1
4 | test4#test.com | 1 | 1
5 | test5#test.com | 9 | 7
5 | test5#test.com | 9 | 4
5 | test5#test.com | 9 | 6
2 | test2#test.com | 5 | 1
5 | test5#test.com | 9 | 8
3 | test3#test.com | 2 | 2
1 | test#test.com | 3 | 2
2 | test2#test.com | 5 | 2
5 | test5#test.com | 9 | 3
Now, selecting randomly any row of the generated table will reflect the probabilities of your winning_odds field.
All you have to do is to order it randomly and get the first record.
9 | test5#test.com | 9 | 2
Regards
I am speculating that the "odds" are not integers and that you want something that has a "9" to be nine times more likely than a "1".
The proper way to do this is with a cumulative sum. Then generate a random value between the min and max of the cumulative sum and choose the record that is in that range. The following query does this in MySQL:
select t.*
from (select t.*,
coalesce((select sum(odds) from t t2 where t2.id < t.id), 0) as cumsum,
const.sumodds
from t cross join
(select rand()*sum(odds) as val from t) const
) t
where val between cumsum and cumsum + t.odds
However, this is doing a non-equijoin and would probably be prohibitively expensive in MySQL. Other databases have the ability to do a cumulative sum in a single query. MySQL does not have an efficient way of doing this.
How to optimize the query depends on certain other factors in the problem. How many different values do "odds" take on? Can you use temporary tables?
I don't have the time right now to write out the solution, but there is a more efficient way. YThe idea is to split the problem into two searches. The first will find which "odds" value wins. The second will find which row wins.
Here are the details:
(1) Summarize the data into a table by the odds. This table would have 11 rows, and contain the "odds" and the "count" for each.
(2) Calculate the sum of "count*odds" for each row, starting at 0 for the first row. You can use the above query as a guide, since this is such a small amount of data it will run quickly.
(3) Calculate a random number as rand()*<sum of all odds>. Now, locate the odds where the number is between cumsum an cumsum+odds.
(4) Now return to the original table and issue a query such as:
select *
from t
where odds = <winning odds>
order by rand()
limit 1
If I understand the question correctly, you are asking how to select a random record from the table. This should work:
SELECT *
FROM tableName
ORDER BY RAND() LIMIT 0,1;
Still now clear how are you planning to user the winning_odds value.