how fast ist it in sql if I would select only the first row with four selects - sql

I'v a problem with look like the same as Union Select Only One Row
But with little different. I'v four selects combined with the union statment.
select top 1 value from (
select 1 as id, value from resource where rkey = 'a'
union
select 2 as id, value from resource where rkey = 'b'
union
select 3 as id, value from resource where rkey = 'c'
union
select 4 as id, value from resource where rkey = 'd'
) as x
order by id
Each of the select statement gives only one or zero rows back. I already would use the first result of all selects. So if the first select returns one row then the other selects should be ignored. And if the second select gives the row back (the first select gives no row back) then the others should be ignored. etc...
My question is: How fast is it in this combination or is there a faster solution?

Or skip the UNION:
select top 1 value
from resource
where rkey in ('a','b','c','d')
order by rkey

If key is indexed your approach (but using UNION ALL) might be the best.
Otherwise try:
select top 1 value
from resource
where rkey in ('a', 'b', 'c', 'd')
order by
case rkey
when 'a' then 1
when 'b' then 2
when 'c' then 3
when 'd' then 4
end

Related

UNION - inconsistent datatype got CLOB

I have a table that look like this
name
value
a
1
b
2
c
3
Of course not with these datas, but I will use it as an example
I need to use it as a inner join, where I can have each name as a column.
It is a defined amount of rows, so that should not be a problem
I have tried to do it as
SELECT
value AS a,
NULL as b
FROM ex
WHERE name = 'a'
UNION
SELECT
NULL as a,
value AS b
FROM ex
WHERE name = 'b'
And so on, but I get the error ORA-00932: inconsistent datatypes: expected - got CLOB
I have also tried with
SELECT
CASE WHEN name = 'a' THEN value ELSE NULL END AS a,
CASE WHEN name = 'b' THEN value ELSE NULL END AS b
FROM ex
WHERE name IN ('a', 'b')
But the result from this is of course
a
b
1
NULL
NULL
2
But I need to eliminate the NULL values, so I only have one row like
a
b
1
2
Does anybody have a good idea of how to solve this problem?
I can of course make 4 joins, but I was thinking, if it could be done in one join, as that will possibly be faster than look in the same table 4 times
I have the impression that you just want to get the value per name. Is this what you aim for:
WITH dat AS
(
SELECT 'a' AS NAME, 1 AS VALUE FROM dual UNION ALL
SELECT 'b', 2 FROM dual UNION ALL
SELECT 'c', 3 FROM dual
)
SELECT *
FROM (SELECT *
FROM dat
PIVOT (MAX(VALUE) FOR NAME IN ('a','b'))); -- list of the ones you need

query to select columns from a row in which another column has certain value only SQL

Consider the following table
id attribute
1 a
1 a
1 b
2 a
2 a
3 c
4 a
I want to select the ids that have attribute of 'a' only, ie 2 and 4.
Cant select 1 because 1 has 'a' and 'b', cant select 3 because it has 'c' only. We select 2 and 4 because it has 'a' value only.
You can use
SELECT id
FROM YourTable
GROUP BY id
HAVING MAX(attribute) = 'a' AND MIN(attribute) = 'a'
AND COUNT(*) = COUNT(attribute)
the
COUNT(*) = COUNT(attribute)
is to discard any id that have NULL attribute as well as a. Remove this if that is not the semantics you want or the column is not nullable anyway.
Please test this:
SELECT id
FROM attribute
GROUP BY id
HAVING
COUNT(DISTINCT attribute) = 1 AND MIN(attribute)= 'a';

Compare 1 field from sub query against other?

I am trying to compare two fields in oracle select query as part of case statement one of which is coming from sub query but I get error.
E.g
select 1 as one,
(select 2 from dual) as two,
case when one=two then 'EQUAL'
else 'NOTEQUAL'
end match
from dual;
Error ORA-00904: TWO invalid identifier
Thoughts how can rewrite this?
Thanks in advance!
You cant use the alias, so you have to rewrite the data source and subquery.
SELECT 1 as one,
(SELECT 2 FROM dual) as two,
CASE WHEN 1 = (SELECT 2 FROM dual)
THEN 'EQUAL'
ELSE 'NOTEQUAL'
END match
FROM dual
Result
one two match
1 2 NOTEQUAL
The problem is you cant use the alias on the same level, you need to do a subquery or a cte
WITH step1 as (
select 1 as one
from dual
), step2 as (
select 2 as two
from dual
)
SELECT case when one=two then 'EQUAL'
else 'NOTEQUAL'
end match
FROM step1
CROSS JOIN step2
Use a simple subquery
Select t.*,
case when one=two then 'EQUAL'
else 'NOTEQUAL'
end match
From (
select 1 as one,
(select 2 from dual) as two
from dual
) t;

How to use LAG function in oracle pl sql until non zero or last row is reached?

I want to write LAG function for table column in such a way that if column value is zero it should lag value for that id if it is again zero for previous row it should LAG again until it reaches a non zero row or last row please help.Thanks in advance
Use LAG() IGNORE NULLS ... combined with a CASE statement:
LAG(
CASE COLUMN_NAME
WHEN 0
THEN NULL
ELSE COLUMN_NAME
END
) IGNORE NULLS OVER ( ORDER BY OTHER_COLUMN )
For example:
WITH DATA ( id, value ) AS (
SELECT 1, 1 FROM DUAL UNION ALL
SELECT 2, 0 FROM DUAL UNION ALL
SELECT 3, 0 FROM DUAL UNION ALL
SELECT 4, 2 FROM DUAL UNION ALL
SELECT 5, 0 FROM DUAL
)
SELECT id,
value,
LAG(
CASE VALUE
WHEN 0
THEN NULL
ELSE VALUE
END
) IGNORE NULLS
OVER ( ORDER BY id )
AS prev_non_zero_value
FROM DATA;
Outputs:
ID VALUE PREV_NON_ZERO_VALUE
---------- ---------- -------------------
1 1
2 0 1
3 0 1
4 2 1
5 0 2
Wouldn't it be simpler to call the same table twice, (for example, call them A and B).
In B, filter out all the rows where the value equals zero, and then do a simple LAG(field,1).
Then just JOIN the two tables.
Voila!

How to write query to return value regardless of existance?

Given this:
with data_row as (select 1 as col_1 from dual)
select 'Y' as row_exists from dual where exists
(select null
from data_row
where col_1 in (2,1))
How can I get this?
Col_1 Row_exists
--------------------
1 Y
2 N
In order to get a row of output, you need a row of input. You want to get the second row with a "2", but there is no table with that value.
The approach is to generate a table that has the values that you want, and then use left outer join to find which match:
with data_row as (
select 1 as col_1
from dual
),
what_i_care_about as (
select 1 as col from dual union all
select 2 from dual
)
select wica.col,
(case when dr.col_1 is NULL then 'N' else 'Y' end) as row_exists
from what_i_care_about wica left outer join
data_row dr
on wica.col = dr.col_1;
You cannot do directly what you want -- which is to create a row for each missing value in the in list. If you have a lot of values and they are consecutive numeric, then you can use connect by or a recursive CTE to generate the values.