I have the following query, that selects places withing given radius:
SELECT *
FROM (
SELECT
group,
name,
111.1111 *
DEGREES(ACOS(LEAST(1.0, COS(RADIANS(".$lat."))
* COS(RADIANS(t1.lat))
* COS(RADIANS(".$lon.") - RADIANS(t1.lon))
+ SIN(RADIANS(".$lat."))
* SIN(RADIANS(t1.lat))))) AS distance
FROM t1
) AS grp
WHERE distance < 10
Is there a way to count how many locations in each group withing this query?
In MySQL you can use HAVING to reduce the number of rows.
SELECT
`group`, COUNT(*) NumOfNames
FROM
(SELECT
`group`,
name,
ST_DISTANCE_SPHERE(POINT('.$lon.', '.$lat.'), POINT(t1.lon, t1.lat)) / 1000 AS distance
FROM
t1
HAVING distance < 10) t2
GROUP BY `group`
Related
I was trying to solve problem in Hackerrank SQL Practice section and stuck in Problem 'Weather Observation Problem 20'.
To find Median, I though of the following approach:
sub-query to count the lower half of the entries.
sub-query to count the upper half of the entries.
Equate these queries together under a WHERE clause (so that an entry has the same number of entries before and after).
QUERY:
select round(s.lat_n,4)
from station s
where (
select round(count(s.id)/2)-1
from station
) = (
select count(s1.id)
from station s1
where s1.lat_n > s.lat_n
);
PLEASE HELP ME OUT WITH THE OPTIMIZED QUERY.
LINK OF PROBLEM STATEMENT : https://www.hackerrank.com/challenges/weather-observation-station-20/problem
When you sort the values the median will be either exactly in the middle (odd number of rows) or the average of two values around the middle (even number of rows). For these values the following is true:
at least half of all values (including itself) are equal or less
at least half of all values (including itself) are equal or greater
When you find that/those values (let's call them candidates), you will need the average of distinct candidate values.
The abouve can be expressed with the following query:
select round(avg(distinct lat_n), 4) as median_lat_n
from station s
cross join (select count(*) as total from station) t
where t.total <= 2 * (select count(*) from station s1 where s1.lat_n <= s.lat_n)
and t.total <= 2 * (select count(*) from station s1 where s1.lat_n >= s.lat_n)
Note that this is a quite slow solution for big tables.
Select round(lat_n,4) from (select lat_n , rank() over(order by lat_n) as rnk from station )a where rnk = (select round((count(lat_n)+1)/2,0) as c from station ) ;
This worked for me
/* SQL ERVER /
SELECT LATNR
FROM
(
SELECT CAST(ROUND(LAT_N,4) AS DECIMAL(17,4)) LATNR, RANK() OVER( ORDER BY LAT_N ASC) IDX
FROM STATION
) AS F
WHERE IDX IN ( CEILING (CAST((SELECT COUNT() +1 FROM STATION) AS FLOAT) /2 ))
Select round(lat_n,4)
from (select lat_n , rank() over(order by lat_n) as Rnk_Col
from station) as Rnk_Table
where Rnk_Col = (select round((count(lat_n)+1)/2,0)
from station);
I found another solution that is more robust than hardcoding the +1 and more efficient than including an IF statement.
with Tbl as (select row_number() over (order by lat_n) rc, lat_n from station)
select cast(avg(lat_n) as Decimal(15,4))
from tbl
where rc = (select ceiling(max(rc)/2.0) from tbl)
select round(lat_n,4) from
(SELECT lat_n,(ROW_NUMBER() OVER(order BY lat_n) ) as "serial_no"
from station ) AS t1
WHERE t1.serial_no = (
select (count(*)+1)/2
from station
)
I used row_number() to create a new column in a table that gives a serial number to ascending ordered lat_n and then displayed the median lat_n value corresponding to middle value of row_number.
First assigns position for each rows using ROW_NUMBER() window function
Second select the middle row if row count is odd else select the two rows in the middle as described here
Finally compute the average and round to 4th decimal point.
If row count is odd, the where conditions return the middle row
Else if row count is even, the where conditions return the two middle rows.
WITH POSITIONED AS (
SELECT
ROW_NUMBER() OVER (ORDER BY LAT_N ASC) AS ROW_NUM,
LAT_N
FROM STATION
)
SELECT ROUND(AVG(LAT_N), 4)
FROM POSITIONED
WHERE ROW_NUM = CEIL((SELECT COUNT(*) FROM STATION) / 2) OR
ROW_NUM = CEIL((SELECT COUNT(*) FROM STATION) / 2 + 0.1)
I am pretty new to SQL queries.
I have a google SQL Search example
SELECT cID,
(6371 * acos
(
cos(radians(51.455643))
* cos(radians(latCord))
* cos(radians(longCord) - radians(7.011555))
+ sin(radians(51.455643))
* sin(radians(latCord))
)
) AS distance
FROM breitengrade
HAVING distance < 50
ORDER BY distance
LIMIT 0, 20
and a own SQL query
SELECT breitengrade.cID
,breitengrade.latCord
,breitengrade.longCord
,Pages.cIsActive
FROM breitengrade
INNER JOIN Pages ON breitengrade.cID = Pages.cID
WHERE cIsActive = '1'
How can I combine these 2 queries into one so that I can get one single result set?
SELECT breitengrade.cID,
breitengrade.latCord,
breitengrade.longCord,
Pages.cIsActive
(6371 * acos
(
cos(radians(51.455643))
* cos(radians(latCord))
* cos(radians(longCord) - radians(7.011555))
+ sin(radians(51.455643))
* sin(radians(latCord))
)
) AS distance
FROM breitengrade
INNER JOIN Pages ON breitengrade.cID = Pages.cID
WHERE cIsActive = '1'
HAVING distance < 50
ORDER BY distance
LIMIT 0, 20
Schema:
place(pid, name, type, lat, lng, deleted)
I want to select count of places, grouping them by their type and
having a distance of < 10 KM from a particular lat, lng
Query:
SELECT count(p.type) as count
FROM (place as p)
where p.deleted != 1
and p.pid in
(
select p2.pid,
IFNULL(acos(sin((18.5236 *pi()/180)) * sin((p2.lat*pi()/180))+cos((18.5236 *pi()/180)) * cos((p2.lat *pi()/180)) * cos(((73.8478 - p2.lng)*pi()/180))) * 6371.009, 0) AS distance
from place p2
having `distance` < 10
)
group by p.type;
Error:
Operand should contain 1 column(s)
That is because I am selecting 2 columns i.e pid and distance in the sub select query. But without using a 2nd select column how can I calculate the distance.
Rewrite your script like this
SELECT count(p.type) AS count,
-- remove this if not necessary
SUM(IFNULL(acos(sin((18.5236 *pi()/180)) * sin((p.lat*pi()/180))+cos((18.5236 *pi()/180)) * cos((p.lat *pi()/180)) * cos(((73.8478 - p.lng)*pi()/180))) * 6371.009, 0)) AS distance
FROM place AS p
WHERE p.deleted != 1
GROUP BY p.type
HAVING SUM(IFNULL(acos(sin((18.5236 *pi()/180)) * sin((p.lat*pi()/180))+cos((18.5236 *pi()/180)) * cos((p.lat *pi()/180)) * cos(((73.8478 - p.lng)*pi()/180))) * 6371.009, 0)) < 10
I have issue in one mysql query
Note I have checked all answer plz don't mark this question as repeat
i have one table with name of "questions" which contain que_id,cat_id, etc fields
I need to fetch 50 records from table which should be random 30 from cat_id=1 and random 20 from cat_id=2
I guess this should do it:
(SELECT * FROM questions
WHERE cat_id = 1
ORDER BY RAND()
LIMIT 30)
UNION ALL
(SELECT * FROM questions
WHERE cat_id = 2
ORDER BY RAND()
LIMIT 20)
(SELECT * FROM `questions` WHERE cat_id=2 and que_id >=
(SELECT FLOOR( MAX(que_id) * RAND()) FROM `questions` ) ORDER BY que_id LIMIT 20) UNION ALL
(SELECT * FROM `questions` WHERE cat_id=1 and que_id >=
(SELECT FLOOR( MAX(que_id) * RAND()) FROM `questions` ) ORDER BY que_id LIMIT 30)
I am trying to generate a random integer for each row I select between 1 and 60 as timer.
SELECT downloads.date, products.*, (FLOOR(1 + RAND() * 60)) AS timer
I have searched and keep coming up to this FLOOR function as how to select a random integer in a range. This is giving me a 1 for every row.
What am I missing?
I am on mysql 5.0.75
Heres the rest of the query I belive it might be a nesting issue
SELECT *
FROM (
SELECT downloads.date, products.*, FLOOR(1 + (RAND() * 60)) AS randomtimer,
(
SELECT COUNT( * )
FROM distros
WHERE distros.product_id = products.product_id
) AS distro_count,
(SELECT COUNT(*) FROM downloads WHERE downloads.product_id = products.product_id) AS true_downloads
FROM downloads
INNER JOIN products ON downloads.product_id = downloads.product_id
) AS count_table
WHERE count_table.distro_count > 0
AND count_table.active = 1
ORDER BY count_table.randomtimer , count_table.date DESC LIMIT 10
This is working for me. Your mysql version maybe?
SELECT id, (FLOOR( 1 + RAND( ) *60 )) AS timer
FROM users
LIMIT 0 , 30
The output of the RAND function will always be a value between 0 and 1.
Try this:
SELECT downloads.date, products.*, (CAST(RAND() * 60 AS UNSIGNED) + 1) AS timer
Old question, but always actual problem.
Here a way to create a MySQL function random_integer() based on manual :
CREATE FUNCTION random_integer(value_minimum INT, value_maximum INT)
RETURNS INT
COMMENT 'Gets a random integer between value_minimum and value_maximum, bounds included'
RETURN FLOOR(value_minimum + RAND() * (value_maximum - value_minimum + 1));
SELECT ALL random_integer(1, 60) AS timer;
I'm running your query and it does give me a random number for each row.... maybe has something to do with the name of the random (timer)?
You can increase the number multiplied by the number of records in the table.
SELECT id,
(FLOOR( (SELECT MIN(id) FROM your_table ) + RAND( ) * 1000000 ) ) AS timer
FROM your_table
LIMIT 0 , 30