LineString to find Vehicle Passing through my 2 Line (4 Points) - sql-server-2008

I have got a task where in I have to Draw 2 lines on Google Map (4 Points) and on Submit event I need to display the Vehicle passing through that points. I am able to draw 2 lines on google map which gives me 4 points in Lat/Longitude format.
Now the main questions is how can I query the database to get the Vehicle passing through two lines. I know I might have to use LineString function in T-SQL but how do i get all the vehicle passing through that lines? Any suggestions is welcome.

Given that I'm not sure how you are representing your "car" or your "lines" and must make assumptions, this code sample might be able to get the ball rolling for you.
It will return a dataset indicating which cars have passed through which lines.
Spatial queries are not my forte; perhaps someone else could offer an optimisation.
-- This is the first line as describer by 2 points
DECLARE #line1 GEOMETRY = geometry::STGeomFromText('LINESTRING(0 10, 10 10)', 0)
-- This is the second line as describer by another 2 points
DECLARE #line2 GEOMETRY = geometry::STGeomFromText('LINESTRING(0 20, 10 20)', 0)
-- #Car1's path is represented as a line that does NOT intersect the 2 defined lines above
DECLARE #Car1 GEOMETRY = geometry::STGeomFromText('LINESTRING(5 0, 5 11)', 0)
-- #Car2's path is represented as a line that DOES intersect that 2 defined lines above
DECLARE #Car2 GEOMETRY = geometry::STGeomFromText('LINESTRING(5 0, 5 23)', 0)
;WITH Lines (LineID, LineGeom) AS
(
SELECT 1, #line1 UNION ALL
SELECT 2, #line2
)
,Cars (CarID, CarGeom) AS
(
SELECT 1, #Car1 UNION ALL
SELECT 2, #Car2
)
SELECT C.CarID
,L.LineID
FROM Cars C
JOIN Lines L ON L.LineGeom.STIntersects(C.CarGeom) = 1

Related

MySQL - How to use JSON_EXTRACT to get values between two indices

I am trying to extract values between 2 indices in a JSON array using mysql JSON_EXTRACT.
SELECT JSON_EXTRACT('[10, 20, 30, 40,50, 60]', '$[1]');
This query will smoothly return 20 as result. But if I want to get all the numbers between, say, 1st and 3rd indices, how do I query it?
I was expecting something like:
SELECT JSON_EXTRACT('[10, 20, 30, 40,50, 60]', '$[1]..$[3]'); // Not the proper syntax
which will return 20,30,40. But not working.
How do I achieve this?
SELECT JSON_EXTRACT('[10, 20, 30, 40,50, 60]', CONCAT('$[', idx, ']'))
FROM ( SELECT 1 idx UNION SELECT 2 UNION SELECT 3 ) src;
Of course the indices range can be provided as list/range and converted to rowset in CTE/subquery.

How to split string with square brackets and commas to columns and rows in mysql

I want to split strings like: [[6, 10, 11, 16], [0.4444444444444445, 53.0, 7.555555555555555, 5.111111111111111]]
to output
id value
---------------------------
6 0.4444444444444445
10 53.0
11 7.555555555555555
16 5.111111111111111
Number of 'ids' in the string varies but there is always value for an 'id'.
This is possible using a stored procedure which chops up the string, creates a (temporary) table, stores the result in said table and returns the table content using a SELECT statement.
However it is unlikely that this is an efficient approach - it will be time consuming to write and execution time will not be good, creating a bottle neck if you pass it a lot of data or if is called repeatedly.
A simpler approach - and the route I would follow - is to do this in your favorite programming language and then store the result in the database.
Alternatively the output of your code could be a query with UNION which would return the desired data structure. Essentially the task is to transpose a two dimensional array and structure the output. If it is not overly large, this would be fast and efficient and could be used as a subquery if you need to combine it with other data.
To give you and idea, the output could be as follows:
SELECT 6 AS id, 0.4444444444444445 AS value
UNION ALL SELECT 10, 53.0
UNION ALL SELECT 11,7.555555555555555
UNION ALL SELECT 16, 5.111111111111111
Put to practical use:
SELECT
sub.id,
sub.value,
info.someFieldFromAnotherTable
FROM
(SELECT 6 AS id, 0.4444444444444445 AS value
UNION ALL SELECT 10, 53.0
UNION ALL SELECT 11,7.555555555555555
UNION ALL SELECT 16, 5.111111111111111
) AS sub
INNER JOIN otherInfoTable info ON info.id = sub.id

SQL Server 2008 Recursive query

FromID ToID
-------------- ----------
1 2
2 3
3 4
5 6
6 7
9 10
I would like to use recursive query in SQL Server 2008 to create an output as
FromID Path
1 1,2,3,4
5 5,6,7
9 9,10
I have been trying to construct a SQL statement using referring to online examples as below
;WITH items AS (
SELECT FromID
, CAST(FromID AS VARCHAR(255)) AS Path
FROM tablex
UNION ALL
SELECT i.FromID
, CAST(Path + '.' + CAST(i.FromID AS VARCHAR(255)) AS VARCHAR(255)) AS Path
FROM tablex i
INNER JOIN items itms ON itms.FromID = i.ToID
)
SELECT *
FROM items
ORDER BY Path
However above doesn't work. Any ideas?
It's not entirely clear to me why your expected output is what it is. The path from 6-10 isn't the complete path to 10: that path starts at ID 5. I've written an example that outputs the full path to illustrate how you'd go about doing that. If you really do want it to start at 6 for some reason, then please clearly state the rule that determines which nodes should appear as starting points in the result set.
I noticed that every ID in your sample data has exactly one predecessor but potentially multiple successors. For that reason, I've chosen to start by identifying the nodes that are endpoints, then work backwards to the starting points. Hopefully the code comments below suffice to explain the rest of what's going on.
declare #TableX table (FromID int, ToID int);
insert #TableX values (1, 2), (2, 3), (3, 4), (5, 6), (6, 7), (6, 9), (9, 10);
with PathCTE as
(
-- BASE CASE
-- Any ID that appears as a "to" but not a "from" is the endpoint of a path. This
-- query captures the ID that leads directly to that endpoint, plus the path
-- represented by that one row in the table.
select
X1.FromID,
[Path] = convert(varchar(max), X1.FromID) + ',' + convert(varchar(max), X1.ToID)
from
#TableX X1
where
not exists (select 1 from #TableX X2 where X2.FromID = X1.ToID)
union all
-- RECURSIVE CASE
-- For every path previously identified, look for another record in #TableX that
-- leads to its starting point and prepend that record's from ID to the overall path.
select
X.FromID,
[Path] = convert(varchar(max), X.FromID) + ',' + PathCTE.[Path]
from
PathCTE
inner join #TableX X on PathCTE.FromID = X.ToID
)
-- Any ID that appears as a "from" but not a "to" is the starting point of one or more
-- paths, so we get all results beginning at one of those points. All other output from
-- PathCTE is partial paths, which we can ignore.
select *
from
PathCTE
where
not exists (select 1 from #TableX X where PathCTE.FromID = X.ToID)
order by
FromID, [Path];
Output:
FromID Path
1 1,2,3,4
5 5,6,7
5 5,6,9,10

MYSQL - Find rows, where part of search string matches part of value in column

I wasn't able to find this anywhere, here's my problem:
I have a string like '1 2 3 4 5' and then I have a mysql table that has a column, let's call it numbers, that look like this:
numbers
1 2 6 8 9 14
3
1 5 3 6 9
7 8 9 23 44
10
I am trying to find the easiest way (hopefully in a single query) to find the rows, where any of the numbers in my search string (1 or 2 or 3 or 4 or 5) is contained in the numbers column. In the give example I am looking for rows with 1,2 and 3 (since they share numbers with my search string).
I am trying to do this with a single query and no loops.
Thanks!
The best solution would be to get rid of the column containing a list of values, and use a schema where each value is in its own row. Then you can use WHERE number IN (1, 2, 3, 4, 5) and join this with the table containing the rest of the data.
But if you can't change the schema, you can use a regular expression.
SELECT *
FROM yourTable
WHERE numbers REGEXP '[[:<:]](1|2|3|4|5)[[:<:]]'
[[:<:]] and [[:<:]] match the beginning and end of words.
Note that this type of search will be very slow if the table is large, because it's not feasible to index it.
Here is a start point (split string function) : http://blog.fedecarg.com/2009/02/22/mysql-split-string-function/ := SplitString(string,delimiter,position)
Create a function so it converts a string to an array := stringSplitted(string,delimiter)
Create a function so it compares two arrays :=arrayIntersect(array1, array2)
SELECT numbers
FROM table
WHERE arrayIntersect(#argument, numbers)
Two function definitions with loops and one single query without any loop
SELECT * FROM MyTable WHERE (numbers LIKE '%1%' OR numbers LIKE '%2%')
or you can also use REGEX something like this
SELECT * FROM events WHERE id REGEXP '5587$'

Complex - returning information that is not found in the database

I have a strange query to perform from a website. I have sets of arrays that contain pertinent ids from a many tables - 1 table per array. For example (the array name is the name of the table):
Array Set 1:
array "q": 1,2,3
array "u": 1,5
array "k": 7
Array Set 2:
array "t": 2,12
array "o": 8, 25
Array Set 3 (not really a set):
array "e": 5
I have another table, Alignment, which is not represented by the arrays. It performs a one to many relationship, allowing records from tables q,u, and k (array set 1, and recorded as relType/relID in the table) to be linked to records from t and o (array set 2, recorded as keyType/keyID) and e (array set 3, recorded as keyType/keyID). Example below:
Table: Alignment
id keyType keyID relType relID
1 e 5 q 1
2 o 8 q 1
3 o 8 u 1
4 t 2 q 2
5 t 2 k 7
6 t 12 q 1
So, in record 6, a record with an id of 12 from table t is being linked to a record with an id of 1 from table q.
I have to find missing links. The ideal state is that each of the ids from array set 1 have a record in the alignment table linking them to at least 1 record from array set 2. In the example, alignment record 1 does not count towards this goal, because it aligns a set 1 id to a set 3 id (instead of set 2).
Scanning the table, you can quickly see that there are some missing ids from array set 1: "q"-3 and "u"-5.
I've been doing this with script, by looping through each set 1 array and looking for a corresponding record, which generates a whole bunch of sql calls and really kills any page that calls this function.
Is there some way I could accomplish this in a single sql statement?
What would I like the results to look like (ideally):
recordset (consisting magically of data that didn't exist in the table):
relType | relID
q 3
u 5
However, I would be elated with even a binary type answer from the database - were all the proper ids found: true or false? (Though the missing records array is required for other functions, but at least I'd be able to choose between the fast and slow options).
Oh, MySQL 5.1.
User Damp gave me an excellent answer using a temporary table, a join, and an IS NULL statement. But it was before I added in the wrinkle that there was a third array set that needed to be excluded from the results, which also ruins the IS NULL part. I edited his sql statement to look like this:
SELECT *
FROM k2
LEFT JOIN alignment
USING ( relType, relID )
HAVING alignment.keyType IS NULL
OR alignment.keyType = "e"
I've also tried it with a Group By relID (i always thought that was a requirement of the HAVING clause). The problem is that my result set includes "q"-1, which is linked to all three types of records ("o","t", and "e"). I need this result excluded, but I'm not sure how.
Here's the sql I ended up with:
SELECT *
FROM k2
LEFT JOIN (
SELECT *
FROM alignment
WHERE keyType != 'e' and
(
(relType = 'q' AND relID IN ( 1, 2, 3 ))
OR
(relType = 'u' AND relID IN ( 1, 5 ))
OR
(relType = 'k' AND relID IN ( 7 ))
)
)A
USING ( relType, relID )
HAVING keyType Is Null
I have to dump the values for the IN qualifiers with script. The key was not to join to the alignment table directly.
You can try to go this route:
DROP TABLE IF EXISTS k2;
CREATE TEMPORARY TABLE k2 (relType varchar(10),relId int);
INSERT INTO k2 VALUES
('q',1),
('q',2),
('q',3),
('u',1),
('u',5),
('k',7);
SELECT * FROM k2
LEFT JOIN Alignment USING(relType,relId)
HAVING Alignment.keyType IS NULL
This should work well for small tables. Not sure about very large ones though...
EDIT
If you wanted to add a WHERE statement the query would be as follow
SELECT * FROM k2
LEFT JOIN Alignment USING(relType,relId)
WHERE Alignment.keyType != 'e'
HAVING Alignment.keyType IS NULL