I have data in PostGIS that have value and geometry. If there is a same value within let say <10 m, I wanna detect or remove that value from my table. Here is the small example:
create table points (id serial primary key, val integer, label2);
select addGeometryColumn('points', 'geom', 1, 'point', 2);
insert into points (id, val, label2, geom) values
(1, 1, aaa, st_geomFromText('POINT(1 1)', 1)),
(2, 1, bbb, st_geomFromText('POINT(1 2)', 1)),
(3, 1, aaa, st_geomFromText('POINT(10 100)', 1)),
(4, 2, ccc, st_geomFromText('POINT(10 101)', 1));
because of data(id) 1 and 2 has the same value and distance<10m, so there just will be:
id |val| source | geom
-----+------------+------
3 | 1 | aaa | xxx
4 | 2 | ccc | xxx
Do you know how to query that in PostGIS?
First, I would consider what are the real requirements? E.g. consider points on a line with 8 meter distance: A, B, C and equal value. Do you want that to be reduced to A and C, or B? Both eliminate duplicates within 10 meters, but the result is different. What about A, B, C, D - would you like result to be A, C, or B, D, or A, D, or maybe B, C? Defining specific criteria is not trivial, and sometimes is hard to implement in SQL.
Or maybe you don't care, and just want to reduce point density? Then it is simpler, just compute snapped = ST_SnapToGrid with appropriate grid size, and group by equal values of snapped, value and chose arbitrary point from each group. Note that this does not guarantee there are no close points (points with similar coordinates can snap to different grid cells) but it does reduce most duplicates and it is very cheap computationally.
Related
I have a list of data, with sequence id 1, 2, 3, ..., 9
I want to insert them into SSRS report in the form of 3x3 table, arranged by sequence id
1 2 3
4 5 6
7 8 9
I should use list, or table, or matrix? Any solution for this arrangement? Thanks
I would typically use a matrix for this. You can calculate the row and column numbers for each row of data in your table and then use that for your row and column groups in the matrix.
Here's an example...
Note: You might not have or want the 'label' field so just swap this out for whichever field you want to show when we get to the report design.
Here's some sample data with the Row and Col calculated
DECLARE #t TABLE (Seq int, Label varchar(10))
INSERT INTO #t VALUES
(1, 'AAAAA'), (5, 'BBBBB'), (10, 'CCCCC'),
(20, 'DDDDD'), (50, 'EEEEE'), (100, 'FFFFF'),
(101, 'GGGGG'), (102, 'HHHHH'), (210, 'IIIII')
SELECT
*
, ColN = (SeqOrder-1) %3
, RowN = (SeqOrder-1) / 3
FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY Seq) AS SeqOrder FROM #t) t
The inner query just assigns the SeqOrder as 1 thru 9. We then use this SeqOrder value to determine the row and column
This gives us the following dataset
Then we just add a matrix to our report
Next, drag the ColN field to the "Columns" placeholder, the RowN field to the "Rows" placeholder and the Label field (or whatever field you want to display) to the "Data" placeholder.
Run the report and you get this
Optionally, you can remove the first row and column (but NOT the associated group) and just leave the data cell.
Now when we run it, we get this.
I have a column names myNumbers in SQL that is a string of json. The json is a list of ints. I want to query that table and only get back records where all ints in the json exist in a list I provide.
| myNumbers |
-------------
| [1, 2, 3] |
| [1, 2] |
| [4, 5, 6] |
| [7, 8, 9] |
Example: I want all records that match numbers (1, 2). I would only get back the second item ([1, 2]). If I wanted all records that matched numbers (1, 2, 3), I would get back both [1, 2, 3] and [1, 2]
What I want to do is this:
select * from myTable where JSON_VALUE(myNumbers, '$') in (1, 2, 3)
But that doesn't work out well. However, if I try the same approach but get the index instead, it works:
select * from myTable where JSON_VALUE(myNumbers, '$[0]') in (1, 2, 3)
I've tried a few other approaches with openjson and json_query but no luck.
Is there some way to accomplish this?
This is an example of Relational Division, see Joe Celko et al.
You can solve this as follows:
Let us assume the required ints are passed through in a single column TVP (I would index it)
SELECT *
FROM myTable
WHERE NOT EXISTS(
SELECT [value]
FROM OPEN_JSON(myNumbers, '$') WITH ([value] int '$')
EXCEPT
SELECT * FROM #tvp)
If you want to hard-code the numbers there is a simpler method:
SELECT *
FROM myTable
WHERE NOT EXISTS(
SELECT [value]
FROM OPEN_JSON(myNumbers, '$') WITH ([value] int '$')
WHERE [value] NOT IN (1,2,3))
We ask for all rows for which: there are no JSON ints which are not in the list, i.e. all of them are. If the size of the list is large, there may be faster ways to do this, but this is the most straightforward.
I have a table named t,
focus, H, Li, Be, B, C
H, 1, 2, 3, 4, 5
Be, 6, 7, 8, 9, 10
I want to write a MySQL query to select columns in this table based on the values of focus column, for example, from table t it will return:
H, Be
1, 3
6, 8
I know it's very easy to write:
select H, Be from t
However, this is not a dynamic resolution if the content of table t changed. For example, assuming table t now is:
focus, H, Li, Be, B, C
B, 5, 0, 0, 4, 4
C, 8, 9, 1, 7, 3
Previous code doesn't work. It still returns the same result instead of:
B, C
4, 4
7, 3
My question is, is it possible, we wrote a MySQL script to select the columns based on the values of focus column?
instead os selected the column based on focus value, why do you select focus based on the column. See the below example
Declare #sql varchar(10),#SQLString varchar(100)
Set #SQL = ‘H’
Set #SQLString = ‘Select focus, ‘+#sql +
‘From tablet
Where focus = ‘+#SQL
Exec #SQLString
I got a TABLE in Excel format like:
SEE LARGE IMAGE HERE
This is a STEN TABLE containing FACTORS (A,B,C,D,E....etc)
Each Factor is like a separate test.
Each Factor i.e. Factor A has a [Raw Score] and a [Sten]
Supposing Factor A, had a question like:
-----------------------------------
Why do humans have Eyes?
The answer options could be like:
a) To Watch movies = [Raw Score] -> 10,
b) To Read Novels = [Raw Score] -> 5,
c) To close them while sleeping = [Raw Score] ->0
So if they Chose a) then, the system will go to the STEN TABLE to get the STEN Equivalent under Factor A, in this case, the sten equivalent will be 4. (See Factor A->Row score 10-> Sten column)
What could be the most practical way to have this STEN TABLE with Factors and their Raw Scores and Stens created?
Something like:
**STEN TABLE**
|
|
**FACTORS (A,B,C,D...)**
/ \
/ \
/ \
/ \
/ \
**[Raw Score] [Sten]**
-----------------------
EDIT 1:
To a larger image, please click here: http://ctrlv.in/459785
Please note that, the stens are not equal for all Factors, though the Raw Scores are the same. i.e. in Factor A, [Raw Score]->3 = [sten]->2 but in Factor C [Raw Score]->3 = [sten]->1 and in Factor F [Raw Score]->1 [sten]->2 whereas in Factor E [Raw Score]->1 = [sten]->1.
Any Suggestion is highly appreciated.
The table structure should be:
Questions
fields: id, factor, text
Answers
fields: id, question_id, text, raw_score
Sten-table(s)
fields: id; factor, raw_score, sten
The id is a unique primary auto-incrment field identifying the line. When you get the answer to a question, you take the factor from the question and the raw_score from the answer and do a simple select on the Sten-table like
SELECT sten FROM sten_table WHERE factor = 'A' AND raw_score = 10
EDIT
The Sten-table would have all lines from your Excel-sheet below eachother:
id, factor, raw_score, sten
1, A, 1, 1
2, A, 2, 1
3, A, .....
...
22, B, 1, 1
23, B, 2, 1
...
I have a MySQL query that I thought was working fine to retrieve all the ancestors of each node, starting from the top node, down to its immediate node. However when I added a 5th level to the nested set, it broke.
Below are example tables, queries and SQL Fiddles:
Four Level Nested Set:
CREATE TABLE Tree
(title varchar(20) PRIMARY KEY,
`tree` int,
`left` int,
`right` int);
INSERT Tree
VALUES
("Food", 1, 1, 18),
('Fruit', 1, 2, 11),
('Red', 1, 3, 6),
('Cherry', 1, 4, 5),
('Yellow', 1, 7, 10),
('Banana', 1, 8, 9),
('Meat', 1, 12, 17),
('Beef', 1, 13, 14),
('Pork', 1, 15, 16);
The Query:
SELECT t0.title node
,(SELECT GROUP_CONCAT(t2.title)
FROM Tree t2
WHERE t2.left<t0.left AND t2.right>t0.right
ORDER BY t2.left) ancestors
FROM Tree t0
GROUP BY t0.title;
The returned result for node Banana is Food,Fruit,Yellow - Perfect. You can see this here SQL Fiddle - 4 Levels
When I run the same query on the 5 level table below, the 5th level nodes come back in the wrong order:
CREATE TABLE Tree
(title varchar(20) PRIMARY KEY,
`tree` int,
`left` int,
`right` int);
INSERT Tree
VALUES
("Food", 1, 1, 24),
('Fruit', 1, 2, 13),
('Red', 1, 3, 8),
('Cherry', 1, 4, 7),
('Cherry_pie', 1, 5, 6),
('Yellow', 1, 9, 12),
('Banana', 1, 10, 11),
('Meat', 1, 14, 23),
('Beef', 1, 15, 16),
('Pork', 1, 17, 22),
('Bacon', 1, 18, 21),
('Bacon_Sandwich', 1, 19, 20);
The returned result for Bacon_Sandwich is Bacon,Food,Meat,Pork which is not the right order, it should be Food,Meat,Pork,Bacon - You can see this here SQL Fiddle - 5 Levels
I am not sure what is happening because I don't really understand subqueries well enough. Can anyone shed any light on this?
EDIT AFTER INVESTIGATION:
Woah!! Looks like writing all this out and reading up about ordering with GROUP_CONCAT gave me some inspiration.
Adding ORDER BY to the actual GROUP_CONCAT function and removing from the end of the subquery solved the issue. I now receive Food,Meat,Pork,Bacon for the node Bacon_Sandwich
SELECT t0.title node
,(SELECT GROUP_CONCAT(t2.title ORDER BY t2.left)
FROM Tree t2
WHERE t2.left<t0.left AND t2.right>t0.right
) ancestors
FROM Tree t0
GROUP BY t0.title;
I still have no idea why though. Having ORDER BY at the end of the subquery works for 4 levels but not for 5?!?!
If someone could explain what the issue is and why moving the ORDER BY fixes it, I'd be most grateful.
First it's important to understand that you have an implicit GROUP BY
If you use a group function in a statement containing no GROUP BY clause, it is equivalent to grouping on all rows.
To make the point more understandable I'll leave out subqueries and reduce the problem to the banana. Banana is the set [10, 11]. The correct sorted ancestors are those:
SELECT "banana" as node, GROUP_CONCAT(title ORDER by `left`)
FROM Tree WHERE `left` < 10 AND `right` > 11
GROUP BY node;
The ORDER BY must be in GROUP_CONCAT() as you want the aggregation function to sort. ORDER BY outside sorts by the aggregated results (i.e. the result of GROUP_CONCAT()). The fact that it worked until level 4 is just luck. ORDER BY has no effect on an aggregate function. You would get the same results with or without the ORDER BY:
SELECT GROUP_CONCAT(title)
FROM Tree WHERE `left` < 10 AND `right` > 11
/* ORDER BY `left` */
It might help to understand what
SELECT GROUP_CONCAT(title ORDER BY left) FROM Tree WHERE … ORDER BY left does:
Get a selection (WHERE) which results in three rows in an undefined order:
("Food")
("Yellow")
("Fruit")
Aggregate the result into one row (implicit GROUP BY) in order to be able to use an aggregate function:
(("Food","Yellow", "Fruit"))
Fire the aggregate function (GROUP_CONCAT(title, ORDER BY link)) on it. I.e. order by link and then concatenate:
("Food,Fruit,Yellow")
And now finally it sorts that result (ORDER BY). As it's only one row, sorting changes nothing.
("Food,Fruit,Yellow")
You can get the result using JOIN or SUB-QUERY.
Using JOIN:
SELECT t0.title node, GROUP_CONCAT(t2.title ORDER BY t2.left) ancestors
FROM Tree t0
LEFT JOIN Tree t2 ON t2.left < t0.left AND t2.right > t0.right
GROUP BY t0.title;
Check this SQL FIDDLE DEMO
Using SUB-QUERY:
SELECT t0.title node,
(SELECT GROUP_CONCAT(t2.title ORDER BY t2.left)
FROM Tree t2 WHERE t2.left<t0.left AND t2.right>t0.right) ancestors
FROM Tree t0
GROUP BY t0.title;
Check this SQL FIDDLE DEMO
OUTPUT
| NODE | ANCESTORS |
|----------------|-----------------------|
| Bacon | Food,Meat,Pork |
| Bacon_Sandwich | Food,Meat,Pork,Bacon |
| Banana | Food,Fruit,Yellow |
| Beef | Food,Meat |
| Cherry | Food,Fruit,Red |
| Cherry_pie | Food,Fruit,Red,Cherry |
| Food | (null) |
| Fruit | Food |
| Meat | Food |
| Pork | Food,Meat |
| Red | Food,Fruit |
| Yellow | Food,Fruit |
In your sub query you had used ORDER BY after WHERE clause which won't affect the output. By default GROUP_CONCAT() function will orders the output string in ascending order of column value. It won't consider you explicit ORDER BY clause.
If you check your output of first query which returns the data in ascending order of title column. So the returned result for node Banana is Food,Fruit,Yellow.
But in your second result for Bacon_Sandwich is Bacon,Food,Meat,Pork because in ascending order Bacon comes first than Food will come.
If you want to order the result based on left column than you have to specify ORDER BY inside the GROUP_CONCAT() function as above. Check my both queries.
I prefer that you use JOIN instead of SUB-QUERY for improving performance.