specify location name if point intersects it MySQL - mysql

I am using MySQL 8.0
I have two tables: location_table, rent_table
location_tables looks like:
location_name polygon
A BLOB
B BLOB
...
polygon is POLYGON datatype.
rent_table looks like:
user_id rent_time rent_location
1 x BLOB
2 x BLOB
...
where rent_location is POINT data type
for each row in rent_table I want to create a column that indicate which location_name it belongs to. If user_id rent_location intersects location_name = A new column would have A
It would look something like this:
user_id rent_time rent_location location_name
1 x BLOB A
2 x BLOB B
...
Thanks in advance!
What I've tried:
I can do one by one by using
select *
, st_intersects(A, Point(ST_X(work_location), ST_Y(work_location))) as location_A
, st_intersects(B, Point(ST_X(work_location), ST_Y(work_location))) as location_B
, st_intersects(C, Point(ST_X(work_location), ST_Y(work_location))) as location_C
from rent_table;
This works when I set A,B,C variable beforehand but I want to get location polygon directly from location_table.
I could use subquery like below:
select *
, st_intersects((select polygon from location_table where location_name = 'A'), Point(ST_X(work_location), ST_Y(work_location))) as location_A
from rent_table;
however I have millions of rows in rent_table therefore I do not want subquery in select statement to run for each of million rows.

You can do:
select
r.*,
l.location_name
from rent r
left join location l on ST_CONTAINS(l.polygon, r.rent_location)

Related

What will be Mysql query for group by and order by dictionary style?

Trying to fetch data and print as like dictionary.
Table:
blog_tags
id name
1 atag1
2 atag2
3 dtag1
4 etag1
5 etag2
6 ctag1
7 ctag2
8 ctag3
9 ztag1
I want the data output as:
A
atag1
atag2
C
ctag1
ctag2
D
dtag1
E
etag1
etag2
Z
ztag1
Started with this:
select name from blog_tags order by name;
what will be mysql query for this?
Try something like this
select name
from (
select distinct upper(substring(name, 1, 1)) as name
from blog_tags
union all
select name
from blog_tags
)
order by name
Edit
If you want to get raw data for application level manipulation, I would suggest querying the db this way
select upper(substring(name, 1, 1)) as key,
name
from blog_tags
order by 1, 2
You can use the bellow query to achieve this as given below
select substr(name,1,1),group_conact(name) from blog_tags group by substr(name,1,1);
This query will group the name's by first character and will group concat the name's as comma separated. You can convert the result from your programming language to array
The output will be like given below
substr(name,1,1) group_conact(name)
A atag1,atag2
C ctag1,ctag2

Join two queries to get particular table format

I have two tables X and Y
SELECT ser.entity_type,ser.param_name
FROM X as ser
where
ser.group_name like '%CRVJL%'
and ser.param_name like '%CBV%'
and ser.entity_type like '%SIGNON%'
SELECT reg.entity_type
FROM REGISTER_TB as reg
where
reg.group_name like '%CRVJL%' and reg.PROV_NAME like'%CBV%' and reg.PROV_NAME like'%-OD-%' and reg.ENTITY_TYPE like '%SIGNON%'
I get some values from table x lets say 4 rows,i have to check if they are present in y or not if not then as -1 and if present then +1
Table should look like this
entity type param_name status
SIGNON CBV6815_I-OD-I 1
SIGNON CBV7815_I-OD-I 1
SIGNON CBV8815_I-OD-I -1
SIGNON CBV9815_I-OD-I 1
we have equal columns
X Y
entity_type entity_type
param-value prov_name
I tried using left join union and right join but its not giving me output as i want.Can anybody help me?
Use this sort of query, you'll have to replace table/field name to match your schema
SELECT a.entity_type, a.param_name, IF(b.status IS NULL, -1, 1) AS 'status'
FROM
X AS a
LEFT OUTER JOIN Y AS b ON a.entity_type=b.entity_type AND a.group_name=b.group_name
WHERE
a.group_name LIKE '%CRVJL%'
AND a.param_name LIKE '%CBV%'
AND a.entity_type LIKE '%SIGNON%'
AND b.prov_name LIKE '%CBV-OD-%'

Select query or select entries that don't start with a number - MySQL

I need to select all entries that do not start with a number between 1-9.
Example Entries:
6300 Dog Lane
Kitty Drive
500 Bird Chrest
800 Tire Road
Johnson Ave
Park Ave
So if I ran a query on the above, I would expect:
Kitty Drive
Johnson Ave
Park Ave
The table is called objects and the column is called location.
Something I tried:
SELECT DISTINCT name, location FROM object WHERE location NOT LIKE '1%' OR '2%' OR '3%' OR '4%' OR '5%' OR '6%' OR '7%' OR '8%' OR '9%';
Unfortunately, that is unsuccessful. Is this possible? If no, I will resort to modifying the data with Perl.
Try this:
SELECT DISTINCT name, location FROM object
WHERE substring(location, 1, 1)
NOT IN ('1','2','3','4','5','6','7','8','9');
or you have to add NOT LIKE before every number:
SELECT DISTINCT name, location FROM object
WHERE location NOT LIKE '1%'
OR location NOT LIKE '2%'
...
You can use the following stntax:
SELECT column FROM TABLE where column NOT REGEXP '^[0-9]+$' ;
SELECT DISTINCT name, location FROM object
WHERE location NOT REGEXP '^[0-9]+$' ;
Try this. It's simpler:
SELECT DISTINCT name, location FROM object WHERE location NOT LIKE '[0-9]%';
What you "tried" needed to have AND instead of OR. Also, DISTINCT is unnecessary.
If you have
INDEX(location)
this would probably be faster than any of the other answers:
( SELECT name, location FROM object
WHERE location < '1'
) UNION ALL
( SELECT name, location FROM object
WHERE location >= CHAR(ORD('9' + 1)) )
This technique only works for contiguous ranges of initial letters, such as 1..9.
A somewhat related question: Should I perform regex filtering in MySQL or PHP? -- it asks about fetching rows starting with 1..9 instead of the opposite.
Try this for SQL Server:
select column_name
from table
where substring(column_name,1,1) not in (1,2,3,4,5,6,7,8,9)
ISNUMERIC should work. (will exclude 0 as well).
Sample code -
ISNUMERIC(SUBSTRING(location, 1, 1)) = 0

How do I select one record per group and left join with another table?

I have one table with two location IDs (pointa and pointb) and how far apart they are. Multiple pairs can be the same distance apart.
Example data:
pointa pointb distance
1 2 250
3 4 250
4 5 250
.....
6 8 500
10 12 500
13 17 500
I want to select one pair from each distance class (one from 250, one from 500 and so on) and join those to another table which contain attributes for that location.
If I were to write this as an algorithm, it would go:
Select one pair at random from each distance class from table distance
join with table data based on distance.pointa=data.location.
Then do the same for pointb such that pointb=data.location
So after the join, I end up with:
pointa pointb data_a data_b
1 2 234.5 440.2
Does anyone have ideas on how I can achieve this?
For now I am doing this using PHP (looking up attributes for a, then b, and then updating a new table. Clearly this is inefficient and I want to learn a better way to do this directly in MySQL.
tia.
getting random rows in SQL can be less than efficient. I'd try something like:
SELECT distance, GROUP_CONCAT(pointa) a, GROUP_CONCAT(pointb) b FROM mytable
GROUP BY distance;
Then in PHP,
while($distance_points= $result->fetch_assoc()){
$distance=$distance_points['distance'];
$as=explode($distance_points['a']);
$random_a=array_rand($as,1);
$bs=explode($distance_points['b']);
$random_b=$bs[array_search($as,$random_a)]; //to get the pair assuming points don't repeat
echo "$distance $random_a $random_b";
}
ETA: Since you have too much data for GROUP_CONCAT, a multiquery solution might work better. Something like:
SELECT DISTINCT distance FROM mytable ORDER BY distance; //get an array with the possible distances
foreach($distances as $d)
$q="SELECT distance, a, b FROM mytable WHERE distance=$d ORDER BY RAND() LIMIT 1";
//run query, retrieve single result and output or store
}
Since you want to get extra info about your locations a and b, you could add that join to $q. Something like:
SELECT distance, a, li1.gps, b, li2.gp2
FROM mytable m
JOIN location_info li1 ON (m.a=li1.id)
JOIN location_info li2 ON (m.b=li2.id)
WHERE distance=$d
ORDER BY RAND() LIMIT 1

Mysql multiple tables select

I've got a table, called for example, "node", from which I need to return values for as shown:
SELECT nid FROM node WHERE type = "book"
After I get a list of values let's say:
|**nid**|
|123|
|12451|
|562|
|536|
Then I need to take these values, and check another table, for rows where column 'path' has values as "node/123", "node/12451" (numbers the previous request returned) in one joined request. It all would be easier if collumn 'path' had simple numbers, without the 'node/'.
And then also count the number of identical i.e. 'node/123' returned.
End result would look like:
nid | path | count(path) | count(distinct path)
123 |node/123| 412 | 123
562 |node/562| 123 | 56
Works fine if done in multiple separated queries, but that won't do.
select a.nid from node a join othertable b
on b.path = concat("node/", a.nid) where type='book'
You can probably do something like the following (nid may require additional conversion to some string type):
SELECT *
FROM OtherTable
JOIN node ON path = CONCAT('node/', nid)
WHERE type = 'book'
Thank you all for your help. Basically, the problem was that I didn't know how to get nid and node/ together, but concat helped.
End result looks something like:
SELECT node.nid, accesslog.path, count(accesslog.hostname), count(distinct accesslog.hostname)
FROM `node`, `accesslog`
WHERE node.uid=1
AND node.type='raamat'
AND accesslog.path = CONCAT('node/', node.nid)
GROUP BY node.nid