I'm having a small issue with sorting the data returned from a query, with the aim of getting the oldest updated value in dataset so that I can update only that record. Here's what I'm doing:
WHERE ROWNUM = 1 AND TABLE1.ID != V_IGNOREID
AND TABLE1.LASTREADTIME = (SELECT MIN(TABLE1.LASTREADTIME) FROM TABLE1)
ORDER BY TABLE1.LASTREADTIME DESC;
It makes no difference as to whether the ORDER BY statement is included or not. If I only use the ROWNUM and equality checks, I get data, but it alternates between only two rows, which is why I'm trying to use the LASTREADTIME data (so that I can modify more than these two rows). Anybody have any thoughts on this, or any suggestions as to how I can use the MIN function effectively?
Cheers
select * from (
-- your original select without rownum and with order by
)
WHERE ROWNUM = 1
EDIT some explanation
I think the order by clause is applied on the resultset after the where clause. So if the rownum = 1 is in the same select statement with the order by, then it will be applied first and the order by will order only 1 row, which will be the first row of the unordered resultset.
Related
I am just wondering if use = sign operator with sub-query instead of IN
Is it correct way ? and meet the oracle standard ?
Example
select column_name from my_table_1 where id = (select max(id) from my_table_2);
The Difference is related to the number of rows returned. If you have only one row returned from nested sql you may prefer both = or in operators. But if multiple rows returned from nested query, use in operator.
So, in your sql example you may prefer using any of the operators. Since, max functions returns only one row.
As you are fetching maximum value from subquery to compare with id, Both(= and IN )will work fine. But If you are trying to fetch more than one row then you have to use IN keyword.
If you have 1 result in sub query you are fine with using = sign, except when data type is wrong, for example , checking with same data type of dummy VARCHAR2(1)
select * from dual where 'X' = (select max(dual.dummy) from dual);
Is similar to using in (also same explain plain)
select * from dual where 'X' in (select max(dual.dummy) from dual);
But checking with different/wrong data type will result with exception ORA-01722 Invalid number
select * from dual where 1 =(select max(dual.dummy) from dual);
UPDATE SCPOMGR.DFUVIEW D
SET D.UDC_NEWDFU = (SELECT (CASE WHEN D1.UDC_CREATIONDATE > ADD_MONTHS (TRUNC(SYSDATE),3)
THEN 1
ELSE 0
END)
FROM SCPOMGR.DFUVIEW D1, SCPOMGR.UDT_GEN_PARAM G
WHERE D.DMDUNIT = D1.DMDUNIT
AND D.DMDGROUP = D1.DMDGROUP
AND D.LOC = D1.LOC
AND G.REGION=VREGION
AND G.JDA_CODE=SUBSTR(D1.DMDUNIT,-2,2)
);
WHAT WILL A SELECT 0 DO?
WILL IT SELECT NO ROWS AND UPDATE THE COLUMN WITH A NULL?
On the right-hand side of the assignment (the value you want to UPDATE) you have a SELECT statement with a CASE expression. There is a subquery (a join with several additional filters). The SELECT statement will return exactly as many rows as there are in the join and satisfy all the additional filters. For some of those rows the SELECT statement will return 1 and for the others, 0.
Do you expect that the subquery (the join with many WHERE conditions) will return exactly one row, then you check the CREATIONDATE and based on that, you update the value to 1 or 0?
In principle, the SELECT statement may return more than one row - in which case you will get a different error message, something about a scalar query (one that is supposed to be scalar, anyway) returning more than one row.
It is also possible that the subquery returns no rows at all - in that case the SELECT statement will return no rows at all, and in such cases the UPDATE means "assign NULL to the column of the left-hand side of the assignment". This is what seems to have happened here.
That is no reason to raise an exception. However, you would get an exception if the column (UDC_NEWDFU) has a NOT NULL constraint.
Since the CASE expression can ONLY return 0 or 1, never NULL, the ONLY way where a NULL assignment is possible is when the subquery (the join with many conditions) returns no rows. In one of the Comments you said that subquery does return rows. I don't believe you. If it does return rows, then I don't believe you that you have an update to NULL being attempted.
I found problem in writing subquery with limit 1 to get the top record.
Here is my problem example.
Table Master(id,set)
Table Detail(id,set,code)
i am trying to get the latest code for each set in Master table.
Following is the query which i tried but got an error that limit 1 is not supported for correlated subqueries and it should contain GROUP By clause.
select id,set,(select code from detail where set=master.set order by id desc limit 1) from master;
And the result wolud be like
please help me if this is wrong way, i am new to this vertica database.
thnk you.
I'm not sure about that particular error, but you can use the rank() analytic function to produce results like this:
select id, set, code from (
select M.id, D.set, D.code, rank() over (partition by D.set order by D.id desc) as rank
from detail as D
right outer join master as M
on D.set = M.set) as ranks
where rank = 1
order by id;
The inner subquery uses the rank() function to assign a rank to each row within a set. The outer query just picks out rows with rank 1.
My subquery returns more than one row and I need the first row and keep my max function
Select ...
Where GHTY_FIRME.FIRME_ID= (Select FIRME_ID
FROM imag_verification_tube
WHERE (numero_dossier = '12004' OR NUMERO_TIRE= '12004')
AND CREE_LE = (select max (CREE_LE)
from tableX where(numero_dossier ='12004' OR
NUMERO_PQDCS= '12004 ')));
Using the rownum pseudocolumn:
Select ...
Where GHTY_FIRME.FIRME_ID= (Select FIRME_ID
FROM imag_verification_tube
WHERE (numero_dossier = '12004' OR NUMERO_TIRE= '12004')
AND CREE_LE = (select max (CREE_LE)
from tableX
where(numero_dossier ='12004'
OR NUMERO_PQDCS= '12004 ')
and rownum < 2));
See also On ROWNUM and Limiting Results.
That said, you can try to optimize the sql. One of the first things I would do is to convert the inner SQLs to joins. Also, depending on your business logic, the or condition could also be elminated.
The issue I face that I need after selecting multiple rows,to loop over each row and fetch those who have some related information to the first row.
Example:
select NAME,ENGLISH_GRADE,FRANCE_GRAE
from (some complex query that have order by and returns 100 rows) WHOLE_ROWS
where
//Here I need to loop over WHOLE_ROWS and make something like that:
//if(currentRow.ENGLISH_GRADE==WHOLE_ROWS(0).ENGLISH_GRADE)
//fetch this row
Basically, you need to join your query to itself. You can do with with a subquery factoring clause:
WITH complex_query AS
( ... complex query here ... )
SELECT
FROM complex_query cq1
WHERE cq1.english_grade = ( SELECT english_grade FROM cq1
WHERE rownum = 1 )
Here is a SQL Fiddle. You could also do this with analytics, but those seem to me more difficult to understand.