Reputation: 880
I'm a bit new to SQL and have a question concerning a case statement in the where clause based on the count(*).
I have a table called CARS, and I am querying for specific Manufacturers and dates in which the car was manufactured on.
From there, let's say I am randomly checking on some cars to ensure that the data is correct so I'd like to first randomly sort the result and then pick out 'x' amount of rows based on how many results I get back (the more results from the query, the more I randomly check)
In my query below, I first get the specific cars from the CARS table, get the count of how many rows that result is, and then I'd like to do a case statement saying: If there are 'x' many cars in the result, here are the first 'y' rows.
select count(*) over() as carcount,
vehicles.*
from (
select *
from CARS
where MANUFACTURER IN (
'BMW',
'Ford',
'Volkswagen',
'Toyota',
'Saab',
'Porsche',
'Hyundai',
'Alfa Romeo'
)
and MANUFACTURED_DATE >= sysdate
and MANUFACTURED_DATE <= (SYSDATE + 30)
and MANUFACTURED_DATE is not null
ORDER BY DBMS_RANDOM.RANDOM
) vehicles
where rownum < (
CASE
WHEN carcount = 1 THEN 1
WHEN carcount = 2 THEN 2
WHEN carcount >= 3 AND carcount <= 4 THEN 2
WHEN carcount >= 5 AND carcount <= 14 THEN 4
WHEN carcount >= 15 AND carcount <= 52 THEN 15
WHEN carcount >= 53 AND carcount <= 365 THEN 25
WHEN carcount > 365 THEN 30
ELSE 0
END
);
When I run my query, I am getting the error:
ORA-00904: "carcount": invalid identifier
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
I am not quite sure why carcount is not a valid identifier and how I can get the first 'x' rows in my random result. I would appreciate any help/advice - thank you in advance!
Upvotes: 0
Views: 1199
Reputation: 222502
carcount
should be computed in the subquery for the query to just work. I would take one step further and use row_number()
rather than rownum
:
select *
from (
select
c.*,
row_number() over(order by dbms_random.random) rn,
count(*) over() cnt
from cars c
where
manufacturer in (
'bmw',
'ford',
'volkswagen',
'toyota',
'saab',
'porsche',
'hyundai',
'alfa romeo'
)
and manufactured_date >= sysdate
and manufactured_date <= sysdate + 30
) c
where rn <= case
when cnt > 365 then 30
when cnt >= 53 then 4
when cnt >= 15 then 15
when cnt >= 5 then 4
when cnt >= 2 then 2
else 1
end
Side notes:
condition and manufactured_date is not null
in the subquery is superfluous - you have inequality predicates on this column already, which filter out null
values
the case
expression can be simplified by ordering the conditions with the high values first - there also are some some redundant conditions, and the target number of rows in the second branch seems unfairly low
it seems like you want <=
rather than <
in the inequality condition on the row number (otherwise, your query would, for example, filter out the results when the subquery returns just 1 row)
Upvotes: 1