MySQL join multiple tables? - mysql

I have 3 tables
tblMarkers
tblReviews
tblImages
I want to return ALL the records from tblMarkers and a count of all the reviews and images for each marker.
To complicate it further it should return all the markers within a radius of a known point.
so the expected result would be
MarkerID-MarkerName-ReviewCount-ImageCount
1223-SomeName-0-1
This is what I have so far and this returns a count of reviews, but I cant get the right SQL to add the count of images
SELECT
`tblMarkers`.`ID`,
`tblMarkers`.`Type`,
`tblMarkers`.`Name`,
`tblMarkers`.`Latitude`,
`tblMarkers`.`Longitude`,
(3959 * acos( cos( radians('45.1') ) * cos( radians( Latitude ) ) * cos( radians( Longitude ) - radians('6') ) + sin( radians('45.1') ) * sin( radians( Latitude ) ) ) )
AS distance,
Count(`tblReviews`.`marker_id`) As reviewCount
FROM
`tblMarkers`
LEFT JOIN `tblReviews` ON `tblMarkers`.`ID` = `tblReviews`.`marker_id`
GROUP BY
`tblMarkers`.`ID`,
`tblMarkers`.`Type`,
`tblMarkers`.`Name`,
`tblMarkers`.`Latitude`,
`tblMarkers`.`Longitude`
HAVING
`distance` < '50'
ORDER BY
distance;
The Images table structure is
ID [primaryKey] (same as tblMarkers.ID)
file
title
How do I add a count of all the images?

Try this:
SELECT M.ID
, M.Type
, M.Name
, M.Latitude
, M.Longitude
, (3959 * acos(cos(radians('45.1')) * cos(radians(M.Latitude )) * cos(radians(M.Longitude) - radians('6')) + sin(radians('45.1')) * sin(radians(M.Latitude )))) AS distance
, IFNULL(COUNT(DISTINCT R.review_id) , 0) AS ReviewCount
, IFNULL(COUNT(DISTINCT I.ID), 0) AS ImageCount
FROM tblMarkers AS M
LEFT JOIN tblReviews AS R ON R.marker_id = M.ID
LEFT JOIN tblImages AS I ON I.marker_id = M.ID
GROUP BY M.ID, M.Type, M.Name, M.Latitude, M.Longitude
HAVING distance < 50
ORDER BY distance
I bet you already know LEFT JOIN. So I used COUNT(DISTINCT R.review_id)) to count all distinct review id's (just make sure that review_id is unique). In case there are no corresponding review and image record for a specific marker record, I used IFNULL(XXX , 0) to display 0.
I used ALIASES to make your query clean and neat. Feel free to ask.

IF ID field of image table is the reference of marker table ID field then the query will be:
SELECT
`tblMarkers`.`ID`,
`tblMarkers`.`Type`,
`tblMarkers`.`Name`,
`tblMarkers`.`Latitude`,
`tblMarkers`.`Longitude`,
(3959 * acos( cos( radians('45.1') ) * cos( radians( Latitude ) ) * cos( radians( Longitude ) - radians('6') ) + sin( radians('45.1') ) * sin( radians( Latitude ) ) ) )
AS distance,
Count(`tblReviews`.`marker_id`) As reviewCount,
Count(`tblImage`.`ID`) As imageCount,
FROM
`tblMarkers`
LEFT JOIN `tblReviews` ON `tblMarkers`.`ID` = `tblReviews`.`marker_id`
LEFT JOIN `tblImage` ON `tblMarkers`.`ID` = `tblImages`.`ID`
GROUP BY
`tblMarkers`.`ID`,
`tblMarkers`.`Type`,
`tblMarkers`.`Name`,
`tblMarkers`.`Latitude`,
`tblMarkers`.`Longitude`
HAVING
`distance` < '50'
ORDER BY
distance;

Related

Query to get nearest distance record

I have following mysql query:
SELECT a.id
, ( 3959 * acos( cos( radians(a.latitude) ) * cos( radians( w.latitude ) )
* cos( radians( w.longitude ) - radians(-a.longitude) )
+ sin( radians(a.latitude) ) * sin(radians(w.latitude)) ) ) distance
FROM global_restaurants a
JOIN webgeocities w
ON w.name = a.locality
AND w.country_code = a.country
AND a.latitude LIKE w.latitude
JOIN states s
ON s.state_code = w.state_code
AND w.country_code = s.country_code
WHERE a.city_id = 0
After execution it returns:
id distance
70 6665.478678743614
70 6496.46971480875
70 6725.900646648246
70 6733.5156930808
90 6969.449661399672
90 7252.889875588891
I want it to only return 2 rows with minimum distance like:
id distance
70 6496.46971480875
90 6969.449661399672
add order by at the end of your query:
order by distance ASC LIMIT 2;
now you calculating the distance but
at end of the query you must sort them and limit the returns row count..
.
NOTE:
i think you have a small mistake on your query
the 3959 is for miles but i think the values are in meter
your full query can be like this:
select a.id, ( 6371000 * acos( cos( radians(a.latitude) ) * cos( radians( w.latitude ) )
* cos( radians( w.longitude ) - radians(-a.longitude) ) + sin( radians(a.latitude) ) * sin(radians(w.latitude)) ) ) AS distance
from `global_restaurants` as a INNER JOIN webgeocities as w ON (w.name = a.locality AND w.country_code = a.country and a.latitude like w.latitude) INNER JOIN
states AS s ON (s.state_code = w.state_code and w.country_code = s.country_code) where a.city_id = '0' ORDER BY distance ASC LIMIT 2;
For simplicity, let's assumed that you have your query in view - stack, then your query should look like this
select stack.* from stack join (
SELECT id, GROUP_CONCAT(distance ORDER BY
distance asc) grouped_distance FROM stack GROUP BY id
) group_distance on group_distance.id=stack.id
where find_in_set(stack.distance,group_distance.grouped_distance)between 1 and 2;

How to get minimum radius location

I have 2 tables
1. feeds => id,name
2. feed_locations => id, feed_id, latitude,longitude,location_name
A feed have multiple locations.
now i want to search near by feed from user current location
I require user latitude or longitude so i fetch from google location and radius
Now i use this mysql query
SELECT
`Feed`.`id`,
`Feed`.`name`,
(3959 * acos (cos ( radians(40.7127837) ) * cos( radians( FeedLocation.latitude ) ) * cos( radians( FeedLocation.longitude ) - radians(-74.00594130000002) ) + sin ( radians(40.7127837) ) * sin( radians( FeedLocation.latitude )))) AS `distance`,
(Select COUNT(id) FROM feed_locations WHERE feed_id = `Feed`.`id`) AS `location_count` FROM `feeds` AS `Feed`
LEFT JOIN `feed_locations` AS `FeedLocation` ON (`FeedLocation`.`feed_id` = `Feed`.`id`)
GROUP BY `Feed`.`id` HAVING distance < 10
ORDER BY `distance` ASC
This query giving me result but
i require minimum distance of the feed_locations from user current location. Distance field give me highest value but i require lowest value from feed_locations table.
My query is working but issue it that :
Like if a single feed have 10 location lik 1m,2m,3m,4m,5m,10m,100m distance. and i want to find 5m distance all feed then it works but it shows me that this feed have 5m. distance from me but result should be 1m distance.
I have created a Fiddle please check http://sqlfiddle.com/#!9/c408e6/5
According to the fiddle in table 1 result is coming that feed1 is 4.02m from my current location but this feed have 2 location in table2 i have show each of location distance .so feed1 one of location is zero mile distance from me but it give result that feed1 is 4.02mile
SELECT
a.id,
a.name,
a.distance,
a.location_count
FROM
(SELECT
`Feed`.`id`,
`Feed`.`name`,
(3959 * acos (cos ( radians(40.7127837) ) *
cos( radians( FeedLocation.latitude ) ) *
cos( radians( FeedLocation.longitude ) -
radians(-74.00594130000002) ) + sin ( radians(40.7127837) ) *
sin( radians( FeedLocation.latitude )))) AS `distance`,
(Select COUNT(id)
FROM feed_locations
WHERE feed_id = `Feed`.`id`) AS `location_count`
FROM `feeds` AS `Feed`
LEFT JOIN `feed_locations` AS `FeedLocation` ON (`FeedLocation`.`feed_id` = `Feed`.`id`)
ORDER BY `distance` ASC) AS a
GROUP BY a.id HAVING distance < 10;
In the fiddle I worked out this query you see and it works, now result is 0. The point is that if you group a not ordered set of records and then you order... you do not order anything. You have to order and then group the ordered set.
Hope it works for you.
Regards

SELECT statements have a different number of columns

I have tried using the code below and it says
The used SELECT statements have a different number of columns
because distance column in added is more in 2nd query .How do I resolve something like this or can I get the order right without distance column?I really appreciate any help.THanks in Advance.
SELECT * FROM
(
SELECT * FROM user u
INNER JOIN employee e ON (u.empid = e.empid)
INNER JOIN awards a ON (u.empid = a.empid)
WHERE u.empid = 123
UNION
SELECT * ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) )+ sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance
FROM user u
INNER JOIN employee e ON (u.empid = e.empid)
INNER JOIN awards a ON (u.empid = a.empid)
HAVING distance < 25
ORDER BY distance
) a
ORDER BY timestamp DESC
It's because your 1st SELECT and 2nd SELECT have varying number of columns, since you introduced Distance in 2nd SELECT.
So try making Distance in 1st query null or 0 as follows.
SELECT * FROM
(
SELECT *, 0 as Distance
FROM user u
INNER JOIN employee e ON (u.empid = e.empid)
INNER JOIN awards a ON (u.empid = a.empid)
WHERE u.empid = 123
UNION
SELECT *, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) )+ sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance
FROM user u
INNER JOIN employee e ON (u.empid = e.empid)
INNER JOIN awards a ON (u.empid = a.empid)
HAVING distance < 25
ORDER BY distance
) a
ORDER BY timestamp DESC
You would fix this by adding distance to the first query:
SELECT * FROM
(
SELECT *, NULL as distance FROM user u
INNER JOIN employee e ON (u.empid = e.empid)
INNER JOIN awards a ON (u.empid = a.empid)
WHERE u.empid = 123
UNION
SELECT *, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) )+ sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance
FROM user u
INNER JOIN employee e ON (u.empid = e.empid)
INNER JOIN awards a ON (u.empid = a.empid)
HAVING distance < 25
ORDER BY distance
) a
ORDER BY timestamp DESC;

Sql query combining

i have two sql queries those are following
1) SELECT a.* FROM modzzz_listing_main as a LEFT JOIN modzzz_listing_rating as b ON a.id=b.gal_id WHERE LTRIM(a.city) = 'Houston' AND a.state = 'TX' AND a.tags LIKE '%Barber Shop%' ORDER BY b.gal_rating_sum DESC LIMIT 0 ,10
2) SELECT zip_code ,( 3959 * acos( cos( radians('41.97734070') ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians('-70.97234344') ) + sin( radians('41.97734070') ) * sin( radians( latitude ) ) ) ) AS distance FROM city_finder WHERE latitude IS NOT NULL AND longitude IS NOT NULL HAVING distance < 20 ORDER BY distance ASC
how can i combine this two queries by the condition `
modzzz_listing_main.zip=city_finder.zip_code
` .i am totally confused..please any one help me..
to see the join easier:
select * from
(
SELECT a.* FROM modzzz_listing_main as a LEFT JOIN modzzz_listing_rating as b ON a.id=b.gal_id WHERE LTRIM(a.city) = 'Houston' AND a.state = 'TX' AND a.tags LIKE '%Barber Shop%' ORDER BY b.gal_rating_sum DESC LIMIT 0 ,10
) queryA
left join
(
SELECT zip_code ,( 3959 * acos( cos( radians('41.97734070') ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians('-70.97234344') ) + sin( radians('41.97734070') ) * sin( radians( latitude ) ) ) ) AS distance FROM city_finder WHERE latitude IS NOT NULL AND longitude IS NOT NULL HAVING distance < 20 ORDER BY distance ASC
) queryB
on queryA.zip=queryB.zip_code
proper formatting
SELECT *
FROM
( SELECT a.*
FROM modzzz_listing_main AS a
LEFT JOIN modzzz_listing_rating AS b ON a.id=b.gal_id
WHERE LTRIM(a.city) = 'Houston'
AND a.state = 'TX'
AND a.tags LIKE '%Barber Shop%'
ORDER BY b.gal_rating_sum DESC LIMIT 0 ,
10 ) queryA
LEFT JOIN
( SELECT zip_code ,
(3959 * acos(cos(radians('41.97734070')) * cos(radians(latitude)) * cos(radians(longitude) - radians('-70.97234344')) + sin(radians('41.97734070')) * sin(radians(latitude)))) AS distance
FROM city_finder
WHERE latitude IS NOT NULL
AND longitude IS NOT NULL HAVING distance < 20
ORDER BY distance ASC ) queryB ON queryA.zip=queryB.zip_code

MySQL distinct or group by in combination with having not giving a result when result is a single row

It seems that my query is not exactly doing what I want. The query gets a result aslong as the result is 2 or more rows. When I get a single row the query is not getting any result.
In the SELECT I can do DISTINCT (ct.name) but this gives the same problem as the group by.
SELECT
ct.name,
( 3959 * acos(cos(radians(52.779716)) * cos(radians( com.gps_lat )) * cos(radians( com.gps_lon ) -
radians(21.84803)) + sin( radians(52.779716) ) * sin( radians( com.gps_lat )))) as distance
FROM cuisine_types as ct
Left joining company to check if a company is attached to the cuisine_type
LEFT JOIN company AS com ON (com.cuisine_type_id = ct.id)
Here I'm grouping the results so no Cuisine Type appears twice.
this only seems to work when the result is 2 or more rows...
GROUP BY ct.name
Here I'm checking if the distance of the company is within the users preferenced search radius
HAVING distance < 20;
for example if I had 'Fastfood', 'Vegan', and 'Healthy' as Cuisine Types, I only want one of each Cuisine Types no matter how many companies in the search distance are related to that Cuisine Type. So I filter the double Cuisine Types away using the GROUP BY I hope this helps with understanding my approach in this query.
NOTE: There is only one Cuisine Type attached to a company.
Full sql query without comments down here
SELECT ct.name, ( 3959 * acos( cos( radians(52.779716) ) * cos(
radians( com.gps_lat ) ) * cos( radians( com.gps_lon ) -
radians(21.84803) ) + sin( radians(52.779716) ) * sin( radians(
com.gps_lat ) ) ) ) as distance FROM cuisine_types as ct LEFT JOIN
company AS com ON (com.cuisine_type_id = ct.id) GROUP BY ct.name
HAVING distance < 20;
Try this:
SELECT
ct.name,
min( ( 3959 * acos( cos( radians(52.779716) ) * cos( radians( com.gps_lat ) ) * cos( radians( com.gps_lon ) - radians(21.84803) ) + sin( radians(52.779716) ) * sin( radians( com.gps_lat ) ) ) ) ) as distance
FROM
cuisine_types as ct
LEFT JOIN company AS com ON (com.cuisine_type_id = ct.id)
GROUP BY
ct.name
HAVING
distance < 20;