Potrzebuję określić, czy dany ciąg może być interpretowany jako liczba (liczba całkowita lub zmiennoprzecinkowa) w instrukcji SQL. Jak w poniższym przykładzie:isnumeric() z PostgreSQL
SELECT AVG(CASE WHEN x ~ '^[0-9]*.?[0-9]*$' THEN x::float ELSE NULL END) FROM test
stwierdziliśmy, że Postgres' pattern matching mogą być wykorzystane do tego celu. I tak zaadaptowałem oświadczenie podane w this place, aby włączyć liczby zmiennoprzecinkowe. To jest mój kod:
WITH test(x) AS (
VALUES (''), ('.'), ('.0'), ('0.'), ('0'), ('1'), ('123'),
('123.456'), ('abc'), ('1..2'), ('1.2.3.4'))
SELECT x
, x ~ '^[0-9]*.?[0-9]*$' AS isnumeric
FROM test;
Wyjście:
x | isnumeric
---------+-----------
| t
. | t
.0 | t
0. | t
0 | t
1 | t
123 | t
123.456 | t
abc | f
1..2 | f
1.2.3.4 | f
(11 rows)
Jak widać, pierwsze dwa egzemplarze (pusty ciąg ''
i jedynym okresem '.'
) zostały błędnie sklasyfikowane jako typ numeryczny (których nie są). W tej chwili nie mogę się do tego zbliżyć. Każda pomoc doceniona!
Aktualizacja podstawie this answer (i uwagach), I dostosowany wzorzec do:
WITH test(x) AS (
VALUES (''), ('.'), ('.0'), ('0.'), ('0'), ('1'), ('123'),
('123.456'), ('abc'), ('1..2'), ('1.2.3.4'), ('1x234'), ('1.234e-5'))
SELECT x
, x ~ '^([0-9]+[.]?[0-9]*|[.][0-9]+)$' AS isnumeric
FROM test;
co daje:
x | isnumeric
----------+-----------
| f
. | f
.0 | t
0. | t
0 | t
1 | t
123 | t
123.456 | t
abc | f
1..2 | f
1.2.3.4 | f
1x234 | f
1.234e-5 | f
(13 rows)
Są jeszcze pewne problemy z naukowego notacja i liczby ujemne, jak widzę teraz.
Czy musisz martwić się liczbami ujemnymi? A co z notacją naukową? –
@muistooshort dzięki jeszcze raz, szczególnie zainteresował mnie ten rodzaj danych wejściowych. To podejście do dopasowywania wzorców nie jest tak proste, jak się spodziewałem. – moooeeeep
Wyrażenie dla liczb ujemnych to po prostu: ''^ -? ([0-9] + [.]? [0-9] * | [.] [0-9] +) $'' poprawne? –