i have a table for some coordination data.
like this:
+------+-------------+-------------+
| fdid | rtime | lat |
+------+-------------+-------------+
| 1 | 1589673600 | -40.1458523 |
| 2 | 1589673601 | -40.1458523 |
| 3 | 1589673602 | -40.1458523 |
| 4 | 1589673603 | -39.8598215 |
| 5 | 1589673604 | -39.8598215 |
| 6 | 1589673605 | -39.8598215 |
| 7 | 1589673606 | -39.8598215 |
| 8 | 1589673607 | -39.8598215 |
| 9 | 1589673608 | -39.8598215 |
| 10 | 1589673609 | -39.8598215 |
+------+-------------+-------------+
there are fields with name lat, representing Latitude
also the rtime is a timestamp.
these data are a vehicle on earth , now i have find when the vehicle go over / or pass the Equator
my query is like this
SELECT
*,
ROUND(rtime/1000,0) grtime,
count(*) acount,
min(rtime) mitime,
max(rtime) matime
FROM `fds_data`
WHERE `lat`<0.5 and lat>-0.5
GROUP BY grtime;
but i thing this is not a complete solution.is there any way for better result !?
In case consistent data (data record each second) you can find Equator pass by next simple query:
SELECT *
FROM `table` `t1`
JOIN `table` `t2` ON `t2`.`rtime` = (`t1`.`rtime` + 1) -- join next record
WHERE `t1`.`lat` * `t2`.`lat` <= 0; -- check Equator pass
Related
I have two table one contains updated_at (can be more than one row) datetime And second contains started_date and stopped_date(one or more records).
I want select updated_at date which should not in between started_date and stopped_date.
Thanks in advance.
I saw the other Question "Check overlap of date ranges in MySQL".
But this not what I want.
user_location
+---+-----+-----+---------------------+
|id | lat | lon | updated_date |
+---+-----+-----+---------------------+
| 1 |16.45|75.45|2018-01-09 12:50:57 |
| 2 |16.85|75.15|2018-01-09 12:53:45 |
| 3 |16.78|75.25|2018-01-09 12:55:48 |
| 4 |16.43|75.35|2018-01-09 13:57:35 |
| 5 |16.48|75.47|2018-01-09 14:59:30 |
| 6 |16.49|75.49|2018-01-10 05:59:58 |
| 7 |16.50|75.50|2018-01-10 07:35:15 |
+---+-----+-----+---------------------+
location_blocked_datetime
+---+--------------------+---------------------+
|id | start_date | stopped_date |
+---+--------------------+---------------------+
| 1 |2018-01-09 05:55:48 | 2018-01-09 07:55:48 |
| 2 |2018-01-09 12:51:48 | 2018-01-09 12:56:48 |
| 3 |2018-01-10 04:30:48 | 2018-01-04 06:55:48 |
+---+--------------------+---------------------+
I want select location from user_location table where updated_date should not be there in start_date and stopped_date.start_date and stopped dates are not fixed and contain more than 1 records
The result of above query should look like this:-
If I want to select locations On 2018-01-09
Result Of Above Query
+---+-----+-----+---------------------+
|id | lat | lon | updated_date |
+---+-----+-----+---------------------+
| 1 |16.45|75.45|2018-01-09 12:50:57 |
| 2 |16.43|75.35|2018-01-09 13:57:35 |
| 3 |16.48|75.47|2018-01-09 14:59:30 |
+---+-----+-----+---------------------+
So I get this right, that the tables are not actually connected and you want to get the records where updated_date is not between any start_date - stopped_date range?
If so, then use not exists like this:
SELECT
l.*
FROM
user_location l
WHERE DATE(l.updated_date) = '2018-01-09'
and not exists (select 1 from location_blocked_datetime
where l.updated_date between start_date and stopped_date)
| id | lat | lon | updated_date |
|----|-----|-----|---------------------|
| 1 | 16 | 75 | 2018-01-09 12:50:57 |
| 4 | 16 | 75 | 2018-01-09 13:57:35 |
| 5 | 16 | 75 | 2018-01-09 14:59:30 |
see it working live in an sqlfiddle
I need a little bit of help with making a complicated query, i will try to explain what i am trying to accomplish down below.
Here is my data
table_one
+---------+---------+----------+----------+
| user_id | poly_id | in | out |
+---------+---------+----------+----------+
| 900 | 1 | 20-12-17 | 20-12-17 |
| 900 | 2 | 21-12-17 | 22-12-17 |
| 900 | 3 | 22-12-17 | 24-12-17 |
| 900 | 1 | 23-12-17 | 26-12-17 |
| 444 | 4 | 24-12-17 | 28-12-17 |
| 444 | 4 | 25-12-17 | 30-12-17 |
| 444 | 5 | 26-12-17 | 01-01-18 |
| 444 | 3 | 27-12-17 | 03-01-18 |
| 900 | 2 | 28-12-17 | 05-01-18 |
| 900 | 1 | 29-12-17 | 07-01-18 |
| 444 | 2 | 30-12-17 | 09-01-18 |
+---------+---------+----------+----------+
table_two
+----+---------+-------------+---------+
| id | name | type | product |
+----+---------+-------------+---------+
| 1 | city 1 | gas station | general |
| 2 | city 2 | workshop | general |
| 3 | city 3 | paint | bikes |
| 4 | city 4 | paint | general |
| 5 | city 5 | gas station | cars |
| 6 | city 6 | gas station | bikes |
| 7 | city 7 | paint | cars |
| 8 | city 8 | workshop | cars |
| 9 | city 9 | gas station | general |
| 10 | city 10 | gas station | cars |
| 11 | city 11 | gas station | general |
+----+---------+-------------+---------+
i have a working solution that looks like this
//results comes from somewhere else, it looks something like this for example:
array (
"user_id" => "poly_id of the last gas station"
"900" => 1,
"444" => 10
)
foreach ($result AS $res ) {
$query = "
SELECT
table_one.name AS name
FROM
`table_one`
LEFT JOIN
`table_two` ON table_one.poly_id = table_two.id
WHERE
`table_two`.type = 'gas station '
AND
table_one.user_id = $res['user_id']
AND
table_one.poly_id != $res['poly_id']
AND
table_one.in >= "some date from'
AND
table_one.out <= 'some date to'
AND
(FIND_IN_SET('general', table_two.product) > 0 OR FIND_IN_SET('cars', table_two.product) > 0 )
ORDER BY out DESC LIMIT 1
";
//if the results is not empty use the result['name']
}
The idea is: I have the user last gas station, but i need to find the previous one between a date range.
As i said, the above example is working just fine, however i need to be able to process multiple results at once, and sometimes the results are ~2000.
Which means 2000+ queries per request.
Is it even possible to somehow optimize this loop of queries into a single one, so I don't do 2000 queries per request ?
If possible, how :D
Thanks.
This query will return result contains user_id with it's last
enter in the given periode.
one thing here because you are
using date not date time if the user exit in the same
day two time you will have two record of that user you can skip the second
record in you code
select
user_id,
in,
out
from table_one t1
INNER JOIN (
select
user_id
max(out) as 'max_out',
from
table_one
where
in >= ? AND
out <= ? AND
ploy_id not in [list_of_unwanted_ploy_id]
-- you can specify any condition here
group by user_id
) l_out on t1.user_id = l_out.user_id and t1.out = l_out.max_out
where
t1.user_id in [list_of_user_id]
Having that table structure & data:
| ID | PARENT | FIELD_1 | FIELD_2 | RATING |
+------------------------------------------+
| 1 | NULL | F1V1 | F2V1 | 10 |
| 2 | 1 | F1V2 | F2V2 | 20 |
| 3 | 2 | F1V3 | F2V3 | 30 |
| 4 | 3 | F1V4 | F2V4 | 40 |
Is there a way of getting a result like this one:
| ID | F_1 | F_2 | P_F_1 | P_F_2 | G_F_1 | G_F_2 | S_R |
+-------------------------------------------------------------+
| 1 | F1V1 | F2V1 | NULL | NULL | NULL | NULL | 10 |
| 2 | F1V2 | F2V2 | F1V1 | F2V1 | NULL | NULL | 30 |
| 3 | F1V3 | F2V3 | F1V2 | F2V2 | F1V1 | F2V1 | 60 |
| 4 | F1V4 | F2V4 | F1V3 | F2V3 | F1V2 | F2V2 | 90 |
What I actually want, as you can see, is for every record if there are parent (P), grandparent (G), etc records (the recursion may go for 4 levels or any other finite number that is already known), the fields of their ancestors prefixed (that can happen programmatically outside of the query) and a SUM (or any other GROUP function) that calculates the values recursively as well.
ex record #4:
ID = 4
FIELD_1 AS F_1 = F1V4
FIELD_2 AS F_2 = F2V4
PARENT_FIELD_1 AS P_F_1 = F1V3
...
GRANDPARENT_FIELD_2 AS G_F_2 = F2V2
SUM_RATING AS S_M = (40 + 30 + 20) = 90**
NOTE:
Even though record #1 is an ancestor of record #4 (grand-grandparent) its rating is not calculated in the sum because it is not contained in the query.
This simplest way:
SELECT t.id,
t.field_1 f_1,
t.field_2 f_2,
p.field_1 p_f_1,
p.field_2 p_f_2,
g.field_1 g_f_1,
g.field_2 g_f_2,
t.rating + COALESCE(p.rating,0) + COALESCE(g.rating,0) s_r
FROM table_name t
LEFT JOIN table_name p
ON p.id = t.parent
LEFT JOIN table_name g
ON g.id = p.parent
And add left joins, additions and field selections to the known level of recursion.
i'm build an exercises web app and i'm working with two tables like this:
Table 1: weekly_stats
| id | code | type | date | time |
|----|--------------|--------------------|------------|----------|
| 1 | CC | 1 | 2015-02-04 | 19:15:00 |
| 2 | CC | 2 | 2015-01-28 | 19:15:00 |
| 3 | CPC | 1 | 2015-01-26 | 19:15:00 |
| 4 | CPC | 1 | 2015-01-25 | 19:15:00 |
| 5 | CP | 1 | 2015-01-24 | 19:15:00 |
| 6 | CC | 1 | 2015-01-23 | 19:15:00 |
| .. | ... | ... | ... | ... |
Table 2: global_stats
| id | exercise_number |correct | wrong |
|----|-----------------|--------|-----------|
| 1 | 138 | 1 | 0 |
| 2 | 246 | 1 | 0 |
| 3 | 988 | 1 | 10 |
| 4 | 13 | 5 | 0 |
| 5 | 5 | 4 | 7 |
| 6 | 5 | 4 | 7 |
| .. | ... | ... | ... |
What i would like is to get MAX(correct-wrong) and MIN(correct-wrong) and now i'm working with this query:
SELECT
exercise_number,
date,
time
FROM weekly_stats AS w JOIN global_stats AS g
ON w.id=g.id
WHERE correct - wrong = (SELECT MAX(correct - wrong) from global_stats)
UNION
SELECT
exercise_number,
date,
time
FROM weekly_stats AS w JOIN global_stats AS g
ON w.id=g.id
WHERE correct - wrong = (SELECT MIN(correct - wrong) from global_stats);
This query is working good, except for one thing: when "WHERE correct - wrong = (SELECT MIN(correct - wrong)[...]" selects more than one row, the row selected is the first but i would like to have returned the most recent (in other words: ordered by datetime(date, time)). Is it possible?
Thanks!
I think you can solve it like this:
SELECT * FROM (
SELECT
1 as sort_column,
exercise_number,
date,
time
FROM weekly_stats AS w JOIN global_stats AS g
ON w.id=g.id
WHERE correct - wrong = (SELECT MAX(correct - wrong) from global_stats)
ORDER BY date DESC, time DESC
LIMIT 1 ) as a
UNION
SELECT * FROM (
SELECT
2 as sort_column,
exercise_number,
date,
time
FROM weekly_stats AS w JOIN global_stats AS g
ON w.id=g.id
WHERE correct - wrong = (SELECT MIN(correct - wrong) from global_stats)
ORDER BY date DESC, time DESC
LIMIT 1) as b
ORDER BY sort_column;
Here is the documentation about how UNION works.
+--------------------+---------------+------+-----+---------+-------+
| ID | GKEY |GOODS | PRI | COUNTRY | Extra |
+--------------------+---------------+------+-----+---------+-------+
| 1 | BOOK-1 | 1 | 10 | | |
| 2 | PHONE-1 | 2 | 12 | | |
| 3 | BOOK-2 | 1 | 13 | | |
| 4 | BOOK-3 | 1 | 10 | | |
| 5 | PHONE-2 | 2 | 10 | | |
| 6 | PHONE-3 | 2 | 20 | | |
| 7 | BOOK-10 | 2 | 20 | | |
| 8 | BOOK-11 | 2 | 20 | | |
| 9 | BOOK-20 | 2 | 20 | | |
| 10 | BOOK-21 | 2 | 20 | | |
| 11 | PHONE-30 | 2 | 20 | | |
+--------------------+---------------+------+-----+---------+-------+
Above is my table. I want to get all records which GKEY > BOOK-2, Who can tell me the expression with mysql?
Using " WHERE GKEY>'BOOK-2' " Cannot get the correct results.
How about (something like):
(this is MSSQL - I guess it will be similar in MySQL)
select
*
from
(
select
*,
index = convert(int,replace(GKEY,'BOOK-',''))
from table
where
GKEY like 'BOOK%'
) sub
where
sub.index > 2
By way of explanation: The inner query basically recreates your table, but only for BOOK rows, and with an extra column containing the index in the right data type to make a greater than comparison work numerically.
Alternatively something like this:
select
*
from table
where
(
case
when GKEY like 'BOOK%' then
case when convert(int,replace(GKEY,'BOOK-','')) > 2 then 1
else 0
end
else 0
end
) = 1
Essentially the problem is that you need to check for BOOK before you turn the index into a numberic, as the other values of GKEY would create an error (without doing some clunky string handling).
SELECT * FROM `table` AS `t1` WHERE `t1`.`id` > (SELECT `id` FROM `table` AS `t2` WHERE `t2`.`GKEY`='BOOK-2' LIMIT 1)