添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Is it possible (in Oracle) to select a column from a table only when some condition is met?

For example, I have a SELECT query that selects columns col1, col2, col3 and I want to select col4 only if some condition is met?

Yes that makes sense. I used CASE WHEN after all and when the condition is not met I set the column to null:

CASE WHEN (SELECT COUNT(*) FROM table2 t2 WHERE t2.id = t1.id) >= 2 THEN (SELECT MIN(col4) FROM table3 t3 WHERE t3.id = t1.id) ELSE null END column4

All those nested selects look horribly inefficient. It’s usually preferrable to use joins instead. I would left join to the other tables.

Something like:

select col1, col2, col3, when t2.id is not null min(t3.col4) else null end col4 from t1 left join t2 on t1.id = t2.id and count(t2.*) >= 2 left join t3 on t1.id = t3.id

That’s the best I could make sense of your obfuscated sample query but the general approach is probably what you’re after.

Cheers,

Joins are more efficient but it’s easier for me to use sub selects when writing a query. It seems more logical to me and I have to think less than with joins.

But in real applications I prefer joins of course :slight_smile:

DISTINCT a.typ , (SELECT COUNT(*) FROM Auta WHERE typ = a.typ) pocet_aut , (SELECT AVG(poplatok_denny) FROM Auta WHERE typ = a.typ) priemerny_denny_poplatok , CASE WHEN (SELECT COUNT(*) FROM Auta WHERE typ = a.typ) >= 2 THEN (SELECT MIN(poplatok_denny) FROM Auta WHERE typ = a.typ) ELSE null END minimalny_denny_poplatok , CASE WHEN (SELECT COUNT(*) FROM Auta WHERE typ = a.typ) >= 2 THEN (SELECT MAX(poplatok_denny) FROM Auta WHERE typ = a.typ) ELSE null END maximalny_denny_poplatok FROM Auta a;

Oh, it’s all the same table you’re working on? That makes it a lot simpler then. I’ve never worked with Oracle before but I can’t see why this wouldn’t work:

select
	count(*) pocet_aut,
	avg(poplatok_denny) priemerny_denny_poplatok,
		when count(*) > 1 then min(poplatok_denny)
		else null
	end minimalny_denny_poplatok,
		when count(*) > 1 then max(poplatok_denny)
		else null
	end maximalny_denny_poplatok,
group by
              

writing that type of repetitive correlated subquery has the potential of being ~seriously~ inefficient

try this –

SELECT DISTINCT a.typ , m.pocet_aut , m.priemerny_denny_poplatok , CASE WHEN m.pocet_aut >= 2 THEN m.minimalny_denny_poplatok ELSE null END minimalny_denny_poplatok , CASE WHEN m.pocet_aut >= 2 THEN m.maximalny_denny_poplatok ELSE null END maximalny_denny_poplatok FROM Auta a INNER JOIN ( SELECT type , COUNT(*) pocet_aut , AVG(poplatok_denny) priemerny_denny_poplatok , MIN(poplatok_denny) minimalny_denny_poplatok , MAX(poplatok_denny) maximalny_denny_poplatok FROM Auta GROUP BY typ ) m ON m.typ = a.typ disgracian:

Oh, it’s all the same table you’re working on? That makes it a lot simpler then. I’ve never worked with Oracle before but I can’t see why this wouldn’t work:

select
	count(*) pocet_aut,
	avg(poplatok_denny) priemerny_denny_poplatok,
		when count(*) > 1 then min(poplatok_denny)
		else null
	end minimalny_denny_poplatok,
		when count(*) > 1 then max(poplatok_denny)
		else null
	end maximalny_denny_poplatok,
group by

Hmm, this gives me this error (and I added semicolon on the end of the query, in Oracle semicolons are required to end each query):

ORA-00936: missing expression

But it’s not important. This is just an assigment for my Oracle class and the query I made works good.

r937:

writing that type of repetitive correlated subquery has the potential of being ~seriously~ inefficient

try this –

SELECT DISTINCT a.typ , m.pocet_aut , m.priemerny_denny_poplatok , CASE WHEN m.pocet_aut >= 2 THEN m.minimalny_denny_poplatok ELSE null END minimalny_denny_poplatok , CASE WHEN m.pocet_aut >= 2 THEN m.maximalny_denny_poplatok ELSE null END maximalny_denny_poplatok FROM Auta a INNER JOIN ( SELECT type , COUNT(*) pocet_aut , AVG(poplatok_denny) priemerny_denny_poplatok , MIN(poplatok_denny) minimalny_denny_poplatok , MAX(poplatok_denny) maximalny_denny_poplatok FROM Auta GROUP BY typ ) m ON m.typ = a.typ

This works the same as my query :slight_smile:

There’s just one typo (type instead of typ).

The reason my query failed is because there was a comma after the last column. Remove that, add the semicolon and you should be right to go. I would be interested in the performance difference between my query and r937’s with the inner join. There probably won’t be any perceptible difference unless the data set is massive, but you can check out the execution plan and/or statistics.

Cheers,

Performance:

My query: 0.02s, 0.01s, 0.02s, 0.02s, 0.02s

rudy’s query: 0.02s, 0.02s, 0.02s, 0.02s, 0.01s

disgracian’s query: 0.01s, 0.01s, 0.00s, 0.02s, 0.02s

EDIT: I have run each query 5 times.

EDIT2: Sorry, now it’s correct.

I would say that the performance results are inconclusive overall. You would either need 5-10 times more data before performance started to really diverge.

That is quite interesting about the order, and I’m not sure why that would happen. You can simply use an ORDER BY clause on any of the SELECT fields if you want to enforce a particular order.

Cheers,