I have a PostgreSQL query that looks like this:
SELECT *,
2 * 3961 * asin(sqrt((sin(radians((latitude - 40.2817993164062) / 2))) ^ 2 + cos(radians(40.2817993164062)) * cos(radians(latitude)) * (sin(radians((longitude - -111.720901489258) / 2))) ^ 2)) as distance,
(SELECT json_agg(deals.*) FROM deals WHERE vendors.id = deals.vendorid) as deals FROM vendors
WHERE ( category = 'Food' )
AND (distance < 80)
AND (nationwide IS FALSE OR nationwide is NULL)
ORDER BY featured ASC, created DESC, distance ASC
I'm getting the distance in miles using the second select part.
The problem is the part that says AND (distance < 80) I get the following error: column "distance" does not exist the weird thing is that if I remove the AND (distance < 80) it works and it also sorts correctly by distance, also the outputted data includes distance, so it's grabbing the distance correctly but for some reason wont let me use the distance as a filter in the WHERE clauses and I can't figure out why.
distance is just an alias. You could try something like:
WITH vendors_distance as (
SELECT *,
2 * 3961 * asin(sqrt((sin(radians((latitude - 40.2817993164062) / 2))) ^ 2 + cos(radians(40.2817993164062)) * cos(radians(latitude)) * (sin(radians((longitude - -111.720901489258) / 2))) ^ 2)) as distance
FROM vendors
WHERE ( category = 'Food' )
AND (nationwide IS FALSE OR nationwide is NULL)
)
SELECT vendors_distance.*,
(SELECT json_agg(deals.*) FROM deals WHERE vendors_distance.id = deals.vendorid) as deals
FROM vendors_distance
WHERE (distance < 80)
ORDER BY featured ASC, created DESC, distance ASC
Related
i was stuck for days in this schema now.
I am trying to populate distance column in a different table from other 2 tables. Inside the table there are lat, long, city id, distance, and location id.
This is the current table that i wanted to populate
This is the two tables that i can get to calculate the distance from
LocationID are the same as ID in the first table
To calculate the distance to the nearest city i calculate it using lat long, this is what my code look like for the nearest distance
select location_id, distance
from (SELECT t.table1.location_id as location_id,
( 6371 * acos( cos( radians(6.414478) ) *
cos( radians(t.table1.latitude::float8) ) *
cos( radians(t.table1.longitude::float8) - radians(12.466646) )
+ sin( radians(6.414478) ) * sin( radians(t.table1.latitude::float8) ) ) ) AS distance
FROM t.table1
INNER JOIN t.table2
on t.table1.location_id = t.table2.id
) km
group by location_id, distance
Having distance < 2000
order by distance limit 20;
but the table only returns null value
I'm using PostgreSQL for this code and the application used for visualising is metabase.
I would recommend you to use ST_Distance function from PostGIS extension for distance calculation instead of doing it yourself. It will be easier and definitely much faster.
Edited: Probably misunderstood the initial intentions.
This should work:
select d.city_id, d.distance, latitude,location_id, longitude
from t.table1
left join lateral (
select city_id, distance from (
select location_id city_id, ( 6371 * acos( cos( radians(table3.latitude) ) *
cos( radians(t.table1.latitude::float8) ) *
cos( radians(t.table1.longitude::float8) - radians(table3.longitude) )
+ sin( radians(table3.latitude) ) * sin( radians(t.table1.latitude::float8) ) ) ) AS distance
from t.table3
) d
where distance < 2000
order by distance
limit 1
) cities on true
Try it out.
Best regards,
Bjarni
To calculate the median for even number of rows, I know I have to divide the RowNum by 2. I don't understand why I need the "+1" and "+2" inside "WHERE RowNum IN ((RowCnt + 1) / 2, (RowCnt + 2) / 2)". Can't I just write "WHERE RowNum IN ((RowCnt) / 2, (RowCnt) / 2)" instead?
with t1 as
(select *,
row_number() over(order by hourly_pay) as RowNum,
count(*) over() as RowCnt
from employee_data)
select *
from t1
WHERE RowNum IN ((RowCnt + 1) / 2, (RowCnt + 2) / 2)
Video of me explaining my confusion: https://streamable.com/mv2vj
SELECT DISTINCT "Users"."id" , "Users".name,
"Users"."surname", "Users"."gender",
"Users"."dob", "Searches"."start_date"
FROM "Users"
LEFT JOIN "Searches" ON "Users"."id" = "Searches"."user_id"
WHERE (SQRT( POW(69.1 * ("Users"."latitude" - 45.465454), 2) + POW(69.1 * (9.186515999999983 - "Users"."longitude") * COS("Users"."latitude" / 57.3), 2))) < 20
AND "Users"."status" = true
AND "Users"."id" != 18
AND "Searches"."activity" = \'clubbing\'
AND "Users"."gender" = \'m\'
AND "Users"."age" BETWEEN 18 AND 30
ORDER BY ABS( "Searches"."start_date" - date \'2016-07-07\' )
For some reasons the above query returns the following error:
for SELECT DISTINCT, ORDER BY expressions must appear in select list
I only want to return unique users but I really don't know what's wrong with it.
Thanks for your help
Just doing what the error message says I would include the expression ABS( "Searches"."start_date" - date '2016-07-07' ) in the SELECT list. No need to change your query logic.
absdiffdate can be discarded later when processing the result.
SELECT DISTINCT "Users"."id" , "Users".name,
"Users"."surname", "Users"."gender",
"Users"."dob", "Searches"."start_date",
ABS( "Searches"."start_date" - date '2016-07-07' ) absdiffdate
FROM "Users"
LEFT JOIN "Searches" ON "Users"."id" = "Searches"."user_id"
WHERE (SQRT( POW(69.1 * ("Users"."latitude" - 45.465454), 2) + POW(69.1 * (9.186515999999983 - "Users"."longitude") * COS("Users"."latitude" / 57.3), 2))) < 20
AND "Users"."status" = true
AND "Users"."id" != 18
AND "Searches"."activity" = 'clubbing'
AND "Users"."gender" = 'm'
AND "Users"."age" BETWEEN 18 AND 30
ORDER BY ABS( "Searches"."start_date" - date '2016-07-07' )
Will this new column results in possibly more records when DISTINCT is applied?
I don't think so because you are subtracting a constant from start_date and for similar start_date corresponds similar outcome.
In Postgres, you can use DISTINCT ON to get one row per user id:
SELECT DISTINCT ON (u."id") u."id", u.name, u."surname", u."gender", u."dob", s."start_date"
FROM "Users" u LEFT JOIN
"Searches" s
ON u."id" = s."user_id"
WHERE (SQRT( POW(69.1 * (u."latitude" - 45.465454), 2) + POW(69.1 * (9.186515999999983 - u."longitude") * COS(u."latitude" / 57.3), 2))) < 20 AND
u."status" = true AND
u."id" != 18 AND "Searches"."activity" = \'clubbing\' AND
u."gender" = \'m\' AND
u."age" BETWEEN 18 AND 30
ORDER BY users.id, ABS(s."start_date" - date \'2016-07-07\' );
Notice how table aliases make the query easier to write and to read.
I am running a query in pgadmin but facing issue column distance does not exist
select f.title, f.longitude, f.latitude, (3959 * cos(cos(radians('52.512452')) * cos(radians(latitude)) * cos(radians(longitude) - radians('13.390931')) + sin(radians('52.512452')) * sin(radians(latitude)))) AS distance from fitness_studio f having distance<1 order by distance desc
Thanks in advance for any help.
Regards,
Aisha
As far as I know postgresql has no way to directly use an alias column in where clause. So you should either try to duplicate the logic:
SELECT
f.title,
f.longitude,
f.latitude,
(3959 * cos(cos(radians('52.512452')) * cos(radians(latitude)) * cos(radians(longitude)
- radians('13.390931')) + sin(radians('52.512452')) * sin(radians(latitude)))) AS distance
FROM fitness_studio f
WHERE (3959 * cos(cos(radians('52.512452')) * cos(radians(latitude)) *
cos(radians(longitude) - radians('13.390931')) +
sin(radians('52.512452')) * sin(radians(latitude)))) < 1
ORDER BY distance DESC
either to use a subquery:
WITH container AS (
SELECT
f.title,
f.longitude,
f.latitude,
(3959 * cos(cos(radians('52.512452')) * cos(radians(latitude)) *
cos(radians(longitude) - radians('13.390931')) +
sin(radians('52.512452')) * sin(radians(latitude)))) AS distance
FROM fitness_studio f)
SELECT *
FROM container
WHERE distance < 1
ORDER BY distance DESC
Please keep in mind that using such subquery may negatively affect execution plan and when your table is large enough execution speed becomes more important than query awkwardness.
PS: Note that ORDER BY may correctly get alias as parameter. Suppose it's cause ORDER BY doesn't affect selected rows, it just rotates them. Same picture with GROUP BY
I have t-sql as follows:
SELECT (COUNT(Intakes.fk_ClientID) * 100) / (
SELECT count(*)
FROM INTAKES
WHERE Intakes.AdmissionDate >= #StartDate
)
FROM Intakes
WHERE Intakes.fk_ReleasedFromID = '1'
AND Intakes.AdmissionDate >= #StartDate;
I'm trying to get the percentage of clients who have releasedfromID = 1 out of a subset of clients who have a certain range of admission dates. But I get rows of 1's and 0's instead. Now, I can get the percentage if I take out the where clauses, it works:
SELECT (COUNT(Intakes.fk_ClientID) * 100) / (
SELECT count(*)
FROM INTAKES
)
FROM Intakes
WHERE Intakes.fk_ReleasedFromID = '1';
works fine. It selects ClientIDs where ReleasedFromID =1, multiplies it by 100 and divides by total rows in Intakes. But how do you run percentage with WHERE clauses as above?
After reading comment from #Anssssss
SELECT (COUNT(Intakes.fk_ClientID) * 100.0) / (
SELECT count(*)
FROM INTAKES
) 'percentage'
FROM Intakes
WHERE Intakes.fk_ReleasedFromID = '1';