You Asked
I have an old and a new query. I need help with the new one. The old query works fine. For the new one, I can't seem to find a way to format two columns (latitude and longitude, I need 6 digits after the decimal) in such a way as they sort correctly.
The is the old query which works correctly, the 'to_number' function in the ORDER BY works in this SQL but I get errors when trying it in the new SQL probably because of the UNION:
SELECT a.platformid,
TRIM(to_char(a.latitude,'90.0000000')) as latitude,
TRIM(to_char(a.longitude,'990.0000000')) as longitude,
a.month,
TRIM(to_char(a.watertemperature, '990.00')) as watertemperature,
TRIM(to_char(a.watersalinity, '990.000')) as watersalinity,
TRIM(to_char(a.currentspeed, '9990.00')) as currentspeed,
a.waterobsdepth
FROM OCEAN a
INNER JOIN SURFACE b
ON a.platformid = b.platformid
AND a.latitude = b.latitude
AND a.longitude = b.longitude
WHERE b.insertiontime >= TO_DATE ('20171107100000', 'yyyymmddhh24miss')
AND b.insertiontime <= TO_DATE ('20171108100000', 'yyyymmddhh24miss')
AND b.distributionCd = 'A'
ORDER BY a.platformid, to_number(a.latitude), to_number(a.longitude), a.waterobsdepth
This is the NEW query which does produce the correct data, but the latitude and longitude for the negative values sorts incorrectly because they are characters. The reason for the new query is to include data from the QUALITY table that was added after the original date. I have tried using to_number but get various errors. I tried not having any formatting in the subqueries and only formatting in the top select, but I get errors for not matching the UNION. I have tried using to_number to format the number but it doesn't keep the 6 digits after the decimal point. Any ideas? The longitude and latitude columns are DATA TYPE = NUMBER (12,7) in the tables.
If I do no formatting with to_char I don't get the 6 digits after the decimal point.
SELECT tb1.platformid,
tb1.latitude,
tb1.longitude,
tb1.month,
tb1.watertemperature,
tb1.watersalinity,
tb1.currentspeed,
tb1.waterobsdepth
FROM
(SELECT a.platformid,
TRIM(to_char(a.latitude, '90.0000000')) as latitude,
TRIM(to_char(a.longitude, '990.0000000')) as longitude,
a.month,
TRIM(to_char(a.watertemperature, '990.00')) as watertemperature,
TRIM(to_char(a.watersalinity, '990.000')) as watersalinity,
TRIM(to_char(a.currentspeed, '9990.00')) as currentspeed,
a.waterobsdepth
FROM OCEAN a, SURFACE b
WHERE b.insertiontime >= TO_DATE ('20171107100000', 'yyyymmddhh24miss')
AND b.insertiontime <= TO_DATE ('20171108100000', 'yyyymmddhh24miss')
AND a.platformid = b.platformid
AND a.latitude = b.latitude
AND a.longitude = b.longitude
AND b.distributionCd = 'A') tb1
UNION
(SELECT c.platformid,
TRIM(to_char(c.latitude, '90.0000000')) as latitude,
TRIM(to_char(c.longitude, '990.0000000')) as longitude,
c.month,
TRIM(to_char(c.watertemperature, '990.00')) as watertemperature,
TRIM(to_char(c.watersalinity, '990.000')) as watersalinity,
TRIM(to_char(c.currentspeed, '9990.00')) as currentspeed,
c.waterobsdepth
FROM OCEAN c, QUALITY d where d.changedate >= to_date('20171107100000','yyyymmddhh24miss')
and d.changedate <= to_date('20171108100000','yyyymmddhh24miss')
and d.observationtime > (to_date('20171107100000','yyyymmddhh24miss') - 30)
and c.platformid = d.platformid
and c.latitude = d.latitude
and c.longitude = d.longitude
and d.distributionCd = 'A')
ORDER BY platformid, latitude, longitude, waterobsdepth;
and Connor said...
All you need to do is defer your formatting until the final query, eg
SQL> create table t ( x number );
Table created.
SQL> insert into t values (1.123);
1 row created.
SQL> insert into t values (2.456);
1 row created.
SQL> insert into t values (3.123);
1 row created.
SQL>
SQL>
SQL> create table t1 ( x number );
Table created.
SQL> insert into t1 values (10.234);
1 row created.
SQL> insert into t1 values (20.324);
1 row created.
SQL> insert into t1 values (30.321);
1 row created.
-- base data sorts fine
SQL>
SQL> select *
2 from
3 ( select x from t
4 union
5 select x from t1
6 )
7 order by 1;
X
----------
1.123
2.456
3.123
10.234
20.324
30.321
6 rows selected.
-- strings do not
SQL>
SQL>
SQL> select *
2 from
3 ( select to_char(x,'fm99.99') char_version from t
4 union
5 select to_char(x,'fm99.99') char_version from t1
6 )
7 order by 1;
CHAR_V
------
1.12
10.23
2.46
20.32
3.12
30.32
6 rows selected.
-- so do string conversion last
SQL>
SQL>
SQL> select to_char(x,'fm99.99') char_version
2 from
3 ( select x from t
4 union
5 select x from t1
6 )
7 order by x;
CHAR_V
------
1.12
2.46
3.12
10.23
20.32
30.32
6 rows selected.
SQL>
Now, if there is the potential for duplicates to occur in your UNION, eg if you had in the source data
20.321
20.322
which would then appear as dups due to the formatting, you can use the ROUND/CEIL/TRUNC/etc functions to get the data cleansed in the inner queries.
Rating
(1 rating)
Is this answer out of date? If it is, please let us know via a Comment