How to select another column in table if first column doesnt have value that i need - sql

I have 1 table where is 2 columns that i need to use at this moment( length and length_to_fault). If length has a null(N/A) value then i need to select value from length_to_fault and opposite.
I also need to sort everything and i can do it with 1 column like this:
select d.* from (select d.*, lead(length::float) over (partition by port_nbr, pair order by add_date) as next_length from diags d where length != 'N/A') d
this select sorts everything except length_to_fault. If 1 record has value in length_to_fault , it will be ignored and it wont show up.
Is there any suggestions?
Maybe its possible to just make these 2 columns into 1? It sounds much logical. But how?

I changed it to select d.* from (select d.*, lead(sum(length::float + length_to_fault::float)) over (partition by port_nbr, pair order by d.add_date) as next_length from diags d)d
i get error : column "d.ip" must appear in the group by clause or be used in an aggregate function.
I dont need to use ip column... I even dont know where to put that ip right now

Related

sql sum 2 column values and sort records by 3 columns

I have columns - ip, port, pair, pair_status, length, length_to_fault, add_date.
I need to sort everything by port, and each port has a pair(A,B,C,D) atleast once. when its sorted, i need to sort even more - i need to sort each pair in exact port.
Currently i have select that does everything that i need but just with a length.
I want to change this fragment so it could check - if length = N/A, then it takes length_to_fault and if length_to_fault = N/A, then it takes length. My idea is just to combine these 2 columns into 1. Also each record has value on one column only(it can be length or length_to_fault). So far i have this-
Select d.*
from (select d.*, lead(length::float) over (partition by port_nbr, pair order by d.add_date) as next_length
from diags d
where length !='N/A'
) d
This works perfectly, but there is records that has N/A in length, but value is inside length_to_fault so this select doesn't take that record. Is there a way to edit this fragment to include length_to_fault too? Maybe i can sum these two columns into one? Also length/length_to_fault is chars in database, so i must change it to float in this select.
You can use a case expression:
Select d.*
from (select d.*,
lead( (case when length <> 'N/A' then length else length_to_fault end)::float) over (partition by port_nbr, pair order by d.add_date) as next_length
from diags d
) d

How to save data in SQL and loop on it?

once i run first query i got the below result:
REQUEST_NO R
---------- -
4309300 A
4300983 C
and i want to compare if R column is different to "C" run second query and do the same for each element that i can have in REQUEST_NO column different to C
SELECT REQUEST_NO
, REQUEST_STS
FROM PORT_REQUEST
WHERE REQUEST_NO IN (SELECT DISTINCT REQUEST_NO
FROM SUB_PORT_REQUEST
WHERE SUBSCRIBER_NO = replace(replace('&CTN','-',''),' ',''));
Enter value for ctn: 5161890110
REQUEST_NO R
---------- -
4309300 A
4300983 C
SELECT ACT_SEQ_NO
FROM SUB_PORT_REQUEST
WHERE REQUEST_NO=&Req_No
AND ROWNUM <=1
ORDER BY ACT_SEQ_NO DESC;
Enter value for req_no: 4309300
ACT_SEQ_NO
----------
91180671
I expect to save in a array or something all values and can be able to iterate on it, can someone help?
One option, if you want to remain in SQL*Plus, is to create a (global temporary?) table, store result of the first query into it, and then rewrite the second query to use those results as
where request_no in (select request_no from my_temporary_table)
Another is to switch to PL/SQL and write a procedure which will accept CTN as a parameter. It (PL/SQL) allows you to use different ways to store results of the first query - into a table (as previously) or an array.
You can combine these to just 1 query by joining the tables. I am not sure I know how to handle the segment "and rownum<=1 Order by ...". Either the order by clause is not needed as rownum<=1 will produce at most 1 row and no matter how you sort it 1 row always comes out the same. Or you expect multiple rows want only want the greatest act_seq_no. If that is the case you need the order by in a sub-query and the rownum predicate on the outer. Assuming the latter we get:
Also assuming the column you refer to as R in description is actually the column port_request.request_sts as R is NOT selected nor is it an alias for any referenced column given.
select act_seq_no
from ( select spr.act_seq_no
from sub_port_request spr
join port_request pr
on (spr.request_no = pr.request_no and
pr.request_sts != 'C'
)
where spr.subscriber_no = replace(replace('&CTN','-',''),' ','')
order by spr.act_seq_no desc
)
where rownum<=1;

Creating new column using nvl

here is my problem. I have an inner query that is working fine, however when I pass the results to outer query I get an error. What I want to accomplish is this, on the outer query, I want to always check if this column (GCO_AD_KNOWLEDGE_TEST_SCORE ) has a value, if it has a value I want to alias it as psi score new column name, additionally if this column does not have a value, I want to check for the second column (PSI_OVERALL_SCORE) if it has a value I want to alias it as PSI Score (new column). anyone want to take stab at this, I will appreciate it.
SELECT
NVL ((CASE WHEN BB.GCO_AD_KNOWLEDGE_TEST_SCORE IS NOT NULL THEN BB.GCO_AD_KNOWLEDGE_TEST_SCORE, ) BB.PSI_OVERALL_SCORE) as PSI SCORE
else null
end
FROM(
SELECT
PARENT_PI_NUMBER,PI_CANDIDATE_NUM,REQUEST_LAST_MODIFIED_DT,Contest_number,
MAX(AA.GCO_AD_KNOWLEDGE_TEST_SCORE) KEEP (DENSE_RANK LAST ORDER BY AA.ARANK) MAX_GCO_AD_KNOWLEDGE_TEST_SCORE,
MAX(AA.PSI_OVERALL_SCORE) KEEP (DENSE_RANK LAST ORDER BY AA.ARANK) MAX_PSI_OVERALL_SCORE
FROM (
select
RANK() OVER (PARTITION BY PARENT_PI_NUMBER ORDER BY REQUEST_LAST_MODIFIED_DT) ARANK
,Contest_number,PARENT_PI_NUMBER,PI_CANDIDATE_NUM,PI_NUMBER,PSI_OVERALL_SCORE,GCO_AD_KNOWLEDGE_TEST_SCORE,REQUEST_LAST_MODIFIED_DT
from
WC_APPLICATION_EVENT_F
WHERE GCO_AD_KNOWLEDGE_TEST_SCORE != '10100'
--WHERE PI_CANDIDATE_NUM = '4639022'and GCO_AD_KNOWLEDGE_TEST_SCORE is not null
) AA
GROUP BY PARENT_PI_NUMBER,PI_CANDIDATE_NUM,REQUEST_LAST_MODIFIED_DT,Contest_number;
--ORDER By PARENT_PI_NUMBER,PI_NUMBER,REQUEST_LAST_MODIFIED_DT;
) BB;
Your inner query still has a semicolon at the end.
MX_GCO_AD_KNOWLEDGE_TEST_SCORE is 31 characters so isn't valid unless you're on 12cR2 (or higher) with long identifiers enabled.
Your nvl/case construction has parentheses and end in the wrong places and has a spare comma with nothing following it.
Your nvl/case are attempting to refer to the original GCO_AD_KNOWLEDGE_TEST_SCORE and PSI_OVERALL_SCORE columns, but those are not exposed by the inline view.
It sounds like you're trying to get:
COALESCE(BB.MX_GCO_AD_KNOWLEDGE_TEST_SCORE, BB.MX_PSI_OVERALL_SCORE) as PSI_SCORE
using the aliases from the inner query, which I've modified from MAX_ to MX_ to make the first one legal.
It's hard to tell if the inner query is actually right with data and expected results, but you said that it's doing what you want.

How to compare ordered datasets with the dataset before?

I have the following query:
select * from events order by Source, DateReceived
This gives me something like this:
I would like to get the results which i marked blue -> When there are two or more equal ErrorNr-Entries behind each other FROM THE SAME SOURCE.
So I have to compare every row with the row before. How can I achieve that?
This is what I want to get:
Apply the row number over partition by option on your table:
SELECT
ROW_NUMBER() OVER(PARTITION BY Source ORDER BY datereceived)
AS Row,
* FROM events
Either you can run a (max) having > 1 option on the result set's row number. Or if you need the details, apply the same query deducting the row nuber with 1.
Then you can make a join on the source and the row numbers and if the error nr is the same then you have a hit.
You can use the partition by as below.
select * from(select
*,row_number()over(partition by source,errornr order by Source, DateReceived) r
from
[yourtable])t
where r>1
You can specify your column names in the outer select.

How to do this query in T-SQL

I have table with 3 columns A B C.
I want to select * from this table, but ordered by a specific ordering of column A.
In other words, lets' say column A contains "stack", "over", "flow".
I want to select * from this table, and order by column A in this specific ordering: "stack", "flow", "over" - which is neither ascending nor descending.
Is it possible?
You can use a CASE statement in the ORDER BY clause. For example ...
SELECT *
FROM Table
ORDER BY
CASE A
WHEN 'stack' THEN 1
WHEN 'over' THEN 2
WHEN 'flow' THEN 3
ELSE NULL
END
Check out Defining a Custom Sort Order for more details.
A couple of solutions:
Create another table with your sort order, join on Column A to the new table (which would be something like TERM as STRING, SORTORDER as INT). Because things always change, this avoids hard coding anything and is the solution I would recommend for real world use.
If you don't want the flexibility of adding new terms and orders, just use a CASE statement to transform each term into an number:
CASE A WHEN 'stack' THEN 1 WHEN 'over' THEN 2 WHEN 'flow' THEN 3 END
and use it in your ORDER BY.
If you have alot of elements with custom ordering, you could add those elements to a table and give them a value. Join with the table and each column can have a custom order value.
select
main.a,
main.b,
main.c
from dbo.tblMain main
left join tblOrder rank on rank.a = main.a
order by rank.OrderValue
If you have only 3 elements as suggested in your question, you could use a case in the order by...
select
*
from dbo.tblMain
order by case
when a='stack' then 1
when a='flow' then 2
when a='over' then 3
else 4
end