Я завернул SQL в функцию, чтобы сделать его проще, чтобы показать некоторые тесты:
SQL Fiddle
Oracle 11g R2 Настройка схемы:
CREATE TABLE mstuser (id, gender, dob) AS
SELECT 1, 'M', SYSDATE - INTERVAL '1' YEAR FROM DUAL
UNION ALL SELECT 2, 'M', SYSDATE - INTERVAL '2' YEAR FROM DUAL
UNION ALL SELECT 3, 'M', SYSDATE - INTERVAL '3' YEAR FROM DUAL
UNION ALL SELECT 4, 'F', SYSDATE - INTERVAL '1' YEAR FROM DUAL
UNION ALL SELECT 5, 'F', SYSDATE - INTERVAL '2' YEAR FROM DUAL
UNION ALL SELECT 6, 'F', SYSDATE - INTERVAL '3' YEAR FROM DUAL
UNION ALL SELECT 7, 'F', SYSDATE - INTERVAL '4' YEAR FROM DUAL
UNION ALL SELECT 8, 'F', SYSDATE - INTERVAL '5' YEAR FROM DUAL
/
CREATE OR REPLACE FUNCTION count_by_compare (
gender_compare mstuser.gender%TYPE,
age_compare_group VARCHAR2
) RETURN NUMBER
AS
user_count NUMBER;
BEGIN
SELECT COUNT(1)
INTO user_count
FROM mstuser a
WHERE ( gender_compare IS NULL
OR UPPER(a.gender) = UPPER(gender_compare)
)
AND ( age_compare_group IS NULL
OR MONTHS_BETWEEN(sysdate, a.dob)/12
BETWEEN TO_NUMBER(SUBSTR(age_compare_group, 1, INSTR(age_compare_group, '-') - 1))
AND TO_NUMBER(SUBSTR(age_compare_group, INSTR(age_compare_group, '-') + 1))
);
return user_count;
END;
/
запроса 1 :
WITH Tests AS (
SELECT 'M' AS gender, '0-1' AS age FROM DUAL
UNION ALL SELECT 'F', '0-6' FROM DUAL
UNION ALL SELECT 'F', '0-1' FROM DUAL
UNION ALL SELECT 'M', '0-6' FROM DUAL
UNION ALL SELECT NULL, '0-2' FROM DUAL
UNION ALL SELECT 'M', NULL FROM DUAL
UNION ALL SELECT 'F', NULL FROM DUAL
UNION ALL SELECT NULL, NULL FROM DUAL
UNION ALL SELECT '', '' FROM DUAL
)
SELECT gender,
age,
SUBSTR(age, 1, INSTR(age, '-') - 1),
SUBSTR(age, INSTR(age, '-') + 1),
count_by_compare(gender, age)
FROM Tests
Results:
| GENDER | AGE | SUBSTR(AGE,1,INSTR(AGE,'-')-1) | SUBSTR(AGE,INSTR(AGE,'-')+1) | COUNT_BY_COMPARE(GENDER,AGE) |
|--------|--------|--------------------------------|------------------------------|------------------------------|
| M | 0-1 | 0 | 1 | 1 |
| F | 0-6 | 0 | 6 | 5 |
| F | 0-1 | 0 | 1 | 1 |
| M | 0-6 | 0 | 6 | 3 |
| (null) | 0-2 | 0 | 2 | 4 |
| M | (null) | (null) | (null) | 3 |
| F | (null) | (null) | (null) | 5 |
| (null) | (null) | (null) | (null) | 8 |
| (null) | (null) | (null) | (null) | 8 |
Кроме того, вам не нужно, чтобы проверить, как != ''
оракул представляет собой пустую строку в качестве NULL
- увидеть окончательный тест выше или пустые сравнения строк ниже:
SELECT CASE WHEN '' = '' THEN 1 ELSE 0 END AS equal,
CASE WHEN '' != '' THEN 1 ELSE 0 END AS not_equal,
CASE WHEN '' IS NULL THEN 1 ELSE 0 END AS is_null,
CASE WHEN '' IS NOT NULL THEN 1 ELSE 0 END AS is_not_null
FROM DUAL
дает результат:
| EQUAL | NOT_EQUAL | IS_NULL | IS_NOT_NULL |
|-------|-----------|---------|-------------|
| 0 | 0 | 1 | 0 |
Вы можете использовать динамический SQL –