sql query to determine if oracle spatial table contains curves - oracle-spatial

I've been struggling to create an Oracle SQL query that will tell me if my SDO table contains curves or arcs. I know that the sdo_elem_info contains the information I need, but I don't know how to use SQL to separate out the etype and interpretation from the sdo_elem_info.
So far, all I have is: select tbl.shape.sdo_elem_info from my_table tbl

You can use the TABLE function to extract the sdo_elem_info_array elements, then pivot that and aggregate the resulting rows to yield a row per element, with a column for offset, etype and interpretation.
Something like this should give you your query... (warning: untested)
WITH elem_info AS (
SELECT
TRUNC((ROWNUM - 1) / 3, 0) element_no
, MAX(DECODE(MOD(ROWNUM, 3), 1, t.COLUMN_VALUE, NULL)) offset
, MAX(DECODE(MOD(ROWNUM, 3), 2, t.COLUMN_VALUE, NULL)) etype
, MAX(DECODE(MOD(ROWNUM, 3), 0, t.COLUMN_VALUE, NULL)) interpretation
FROM my_table tbl
, TABLE(tbl.shape.sdo_elem_info) t
GROUP BY TRUNC((ROWNUM - 1) / 3, 0)
)
SELECT DECODE(COUNT(*), 0, 'false', 'true')
FROM elem_info ei
WHERE ei.etype IN (1005, 2005)
OR ei.interpretation IN (2, 4)

Related

sql alias to function for reuse in select

im trying to make the query more efficient, is there a way to use an alias in order to call regexp_substr only once?
this is the sql query:
SELECT *,
(SUBSTRING(REGEXP_SUBSTR(A, '(://([a-zA-Z0-9]+):)', 1, 1, 'c'), 4, LENGTH(REGEXP_SUBSTR(A, '(://([a-zA-Z0-9]+):)', 1, 1, 'c')) - 4)) as custom
FROM table
No need for a second regexp_substr, simply use 2 argument SUBSTRING. (I.e. substring from position 4 to the end):
SELECT *,
SUBSTRING(REGEXP_SUBSTR(A, '(://([a-zA-Z0-9]+):)', 1, 1, 'c'), 4) as custom
FROM table
https://docs.snowflake.com/en/sql-reference/functions/substr.html

USING CASE AS PART OF JOIN ORACLE SQL

I have a query in Oracle SQL Developer to grab data from a raw table (all the data on the raw table are varchars) where I need to "clean" the data when I select it. Have to use a CASE statement to get the store number because sometimes that data isn't in the STORENBR column but can be found in a substring of another column -
SELECT
CASE WHEN m.STORENBR = '0' AND (SUBSTR(m.SENDING_QMGR, 1, 5) = 'PDPOS')
THEN TO_NUMBER((SUBSTR(m.SENDING_QMGR, 8, 4)))
WHEN m.STORENBR = '0' AND (SUBSTR(m.SENDING_QMGR, 1, 8) = 'PROD_POS')
THEN TO_NUMBER((SUBSTR(m.SENDING_QMGR, 9, 4)))
ELSE TO_NUMBER(NVL(m.STORENBR, '0'))
END AS STORENBR,
TO_NUMBER(NVL(m.CONTROLNBR,'0')) AS CONTROLNBR,
TO_NUMBER(NVL(m.LINENBR,'0')) AS LINENBR,
TO_DATE(m.TRANDATE,'YYYY-MM-DD') AS TRANDATE,
TO_NUMBER(NVL(m.NUMMISPRINTED,'0.00'),'99.99') AS NUMMISPRINTED
FROM MISPRINTS_RAW m
WHERE TO_DATE(m.TRANDATE,'YYYY-MM-DD') = '15-MAR-21'
ORDER BY m.STORENBR;
Now I need to also pull an account number from another table (TRANSACTIONS t - not a raw table, so I don't need any CASE or TO_NUMBER to pull data) but I need to join that table on STORENBR, CONTROLNBR, and LINENBR. So how do I use that CASE statement as part of the join to JOIN m.STORENBR on t.STORENBR?
Even if I am not sure about the data structure the following statement should be helpful.
The table with the raw data is "converted" in a subselect, so that a normal join is possible.
SELECT *
FROM (SELECT CASE
WHEN m.storenbr = '0'
AND ( Substr(m.sending_qmgr, 1, 5) = 'PDPOS' ) THEN
To_number(
( Substr(m.sending_qmgr, 8, 4) ))
WHEN m.storenbr = '0'
AND ( Substr(m.sending_qmgr, 1, 8) = 'PROD_POS' ) THEN
To_number(( Substr(m.sending_qmgr, 9, 4) ))
ELSE To_number(Nvl(m.storenbr, '0'))
END AS STORENBR,
To_number(Nvl(m.controlnbr, '0')) AS CONTROLNBR,
To_number(Nvl(m.linenbr, '0')) AS LINENBR,
To_date(m.trandate, 'YYYY-MM-DD') AS TRANDATE,
To_number(Nvl(m.nummisprinted, '0.00'), '99.99') AS NUMMISPRINTED
FROM misprints_raw m) m1,
TRANSACTION t
WHERE t.storenbr = m1.storenbr
AND t.controlnbr = m1.controlnbr
AND t.linenbr = m1.linenbr
AND m1.trandate = DATE '2021-03-15'
ORDER BY m1.storenbr;

Group elements of a column into mulitple subgroups SQL

I am looking at different breeds of cattle and their AnimalTypeCode , BreedCateoryID and resultant Growth.
I have the following query
SELECT DATEPART(yyyy,[KillDate])
,[AnimalTypeCode]
,AVG([Growth])
,[BreedCategoryID]
FROM [dbo].[tblAnimal]
WHERE (AnimalTypeCode='C'
or AnimalTypeCode= 'E')
GROUP BY DATEPART(yyyy,[KillDate])
,[AnimalTypeCode]
,[BreedCategoryID]
GO
This query is good and gives me almost what I want, but BreedCategoryID is numbered 1 through 7 and I would like to group them:
(1 = Pure Dairy),
(2 and 3 = Dairy)
(4, 5, 6 and 7 = Beef)
So instead of getting the mean Growthrate for each BreedCategoryID I would like to get the average for Pure Dairy, Dairy, and Beef.
Any help greatly appreciated!
You can assign a new "variable" using cross apply in the from clause:
SELECT YEAR(KillDate]), a.AnimalTypeCode, v.grp,
AVG([Growth])
FROM [dbo].[tblAnimal] a CROSS APPLY
(VALUES (CASE WHEN a.BreedCategoryID IN (1) THEN 'Pure Dairy'
WHEN a.BreedCategoryID IN (2, 3) THEN 'Dairy'
WHEN a.BreedCategoryID IN (4, 5, 6, 7) THEN 'Beef'
END)
) as v(grp)
WHERE a.AnimalTypeCode IN ('C', 'E')
GROUP BY YEAR(KillDate]), a.AnimalTypeCode, v.grp;
Note that I also introduced table aliases and qualified all the column references.
Do the calculations in a derived table (the subquery). GROUP BY its result:
select killyear, [AnimalTypeCode], AVG([Growth]), BreedCat
(
SELECT DATEPART(yyyy,[KillDate]) killyear
,[AnimalTypeCode]
,[Growth]
,case when [BreedCategoryID] = 1 then 'Pure Dairy'
when [BreedCategoryID] in (2, 3) then 'Dairy'
when [BreedCategoryID] in (4, 5, 6, 7) then 'Beef'
end BreedCat
FROM [dbo].[tblAnimal]
WHERE (AnimalTypeCode='C'
or AnimalTypeCode= 'E')
) dt
GROUP BY killyear
,[AnimalTypeCode]
,BreedCat

SQL ARRAY: Select ID from my_table where "arrayvalue" = "defined_arrayvalue"

This is a beginner-question relating arrays. I hope the answer is simple.
The example is taken from Oracle Spatial, but I think it is valid for all arrays.
I have this SELECT:
SELECT
D.FID
, D.GEOM.SDO_ELEM_INFO -- column GEOM contains spatial data
FROM
my_table D
I get this result:
73035 MDSYS.SDO_ELEM_INFO_ARRAY(1, 2, 1)
73036 MDSYS.SDO_ELEM_INFO_ARRAY(1, 4, 3, 1, 2, 1, 11, 2, 2, 19, 2, 1)
73037 MDSYS.SDO_ELEM_INFO_ARRAY(1, 2, 1)
Now I want to SELECT all rows where (1,2,1) is defined:
SELECT
D.FID
, D.GEOM.SDO_ELEM_INFO
FROM
my_table D
WHERE
-- Pseudo-Code is following
D.GEOM.SDO_ELEM_INFO is "(1, 2, 1)";
So, in simple words: "array_from_row = defined_array".
I found a lot about IMPLODE and TABLE and COLLECT etc. But how to define a clause on two arrays?
Thanks for help!
Try IN clause, you can also use both
SELECT
D.FID
, D.GEOM.SDO_ELEM_INFO
FROM
my_table D
WHERE
D.GEOM.SDO_ELEM_INFO in (1, 2, 1) or ( D.GEOM.SDO_ELEM_INFO = 1 or D.GEOM.SDO_ELEM_INFO = 2 or D.GEOM.SDO_ELEM_INFO = 3);

SQL: Don't display anything unless all values match

So in this case I want to display every ID where the corresponding value is 1. However, in the case below where the ID is 4, I don't want it to display the 4's where the value is 1, I just want it to not show 4 at all. If I do a WHERE value LIKE '1', it'll show me the two IDs of 4 where the value is 1. Is there a way to not show 4 at all? Thanks in advance.
ID:.......1...2...3...4...4...4...5
Value:....1...1...1...1...2...1...1
(This is on Microsoft SQL Server management studio by the way)
If you just want the ids, then use aggregation:
select id
from t
group by id
having min(value) = 1 and max(value) = 1;
To add on Gordon's answer
I would add a count since it seems your data has multiple 1s in that case if you have two 1s you'd have it as both min and max
select id
from t
group by id
having min(value) = 1 and max(value) = 1 and count(value) = 1;
You could also use
select id from t group by id having sum(value) = 1 and count(value) = 1;
with cte as (
select * from (values
(1, 1),
(2, 1),
(3, 1),
(4, 1),
(4, 2),
(4, 1),
(5, 1)
) as x(ID, Value)
)
select *
from cte
where ID not in (
select ID
from cte
where Value > 1
);