Where clause based on priority - sql

Consider Following table named A:
State City Rank
S C 1
AB C1 2
* C2 3
I want to select all columns such that
If State is AB return all such rows
If condition 1 is not met return all rows with state *. If condition 1 is met don't look on to this condition
As per above example I should get row 2. I tried several things like
select state
case when a.state = 'AB' then 1
when a.state = '*' then 2
end as priority from A where state in ('AB','*') order by priority
But above query returns more than one rows. I want exact one row which matches above condition.
Please help
EDIT1:
I want to avoid sub queries due to performance issues.

Try this:
select * from A
where state=case
when exists(select * from A where state='AB') then 'AB'
else '*'
end
Here is the SQL Fiddle demonstrating the above.

Related

Using case statement to compare columns

I'd like to use a case statement to compare multiple rows on 2 columns. For example, if row 1 column 1 and row 2 column 1 match but row 1 column 2 and row 2 column 2 don't, then xx. I have
CASE
WHEN (pprof.description = pprof.description and PCtrl.[sequence] <> PCtrl.[sequence])
THEN xx
but that doesn't return any values, which I know to be incorrect. I'm new to SQL so apologies if I've got this all wrong.
Edit:
Here's some sample data:
Column 1
Column 2
Column 3
123
-A
-No
123
-B
-Yes
Can't figure out the formatting here but there are 3 columns of data above. I'd like the case statement to evaluate whether column 1 match in 2 different rows (i.e., 123 = 123) and also whether column 2 doesn't (A <> B) and if both those conditions are true, return a value in column 3 (in my case, make the No a Yes, since 123-B is Yes). It might be worth noting that the "Yes" and "No" themselves are built into the larger case statement here:
(CASE WHEN tenure.description not in ('casual','co-op','fswep') THEN CASE WHEN (pprof.description = pprof.description and PCtrl.[sequence] <> PCtrl.[sequence])
THEN CASE WHEN (PEmp.Employee_Number = PEmp3.Supervisor_Number) THEN 'Yes' ELSE 'No' END END END) as 'People Manager'
You will want to do a self join here. Without seeing your data, I can't really give you an answer, but you want something like this.
Update A
Set column_3 = 'YES' /* or put CASE statement here /*
FROM pprof A
INNER JOIN pprof B
ON a.description = b.description
AND a.sequence != b.sequence
You may need more join conditions depending on the form of your data and what you want.

Compare two unrelated tables sql

We're dealing with geographic data with our Oracle database.
There's a function called ST_Insertects(x,y) which returns true if record x intersects y.
What we're trying to do is, compare each record of table A with all records of table B, and check two conditions
condition 1 : A.TIMEZONE = 1 (Timezone field is not unique)
condition 2 : B.TIMEZONE = 1
condition 3 : ST_Intersects(A.SHAPE, B.SHAPE) (Shape field is where the geographical information is stored)
The result we're looking for is records ONLY from the table A that satisfy all 3 conditions above
We tried this in a single select statement but it doesn't seem to make much sense logically
pseudo-code that demonstrates a cross-join:
select A.*
from
tbl1 A, tbl2 B
where
A.TIMEZONE = 1 and
B.TIMEZONE = 1 and
ST_Intersects(A.SHAPE, B.SHAPE)
if you get multiples, you can put a distinct and only select A.XXX columns
With a cross-join rows are matched like this
a.row1 - b.row1
a.row1 - b.row2
a.row1 - b.row3
a.row2 - b.row1
a.row2 - b.row2
a.row2 - b.row3
So if row 1 evaluates to true on multiple rows, then just add a distinct on a.Column1, etc.
If you want to use the return value from your function in an Oracle SQL statement, you will need to change the function to return 0 or 1 (or 'T'/'F' - some data type supported by Oracle Database, which does NOT support the Boolean data type).
Then you probably want something like
select <columns from A>
from A
where A.timezone = 1
and exists ( select *
from B
where B.timezone = 1
and ST_intersects(A.shape, B.shape) = 1
)

Check string starts with specific letter

Please help me with below query , I want to check if string is starts with 'G' or 'F' in where condition along with existing condition. here is the query
first query :-
SELECT Top 1 LC_ID, ISNULL(LC_UD, 0) as Record
FROM CONTRACT
WHERE LC_ID = 'F01'
output
F01 | 1 ( if available) else no record will be return.
second query:
IF LC_ID starts with 'F%' or 'G%'
How i can integrate both the query into one so that if there is no record available for 'F01' value, it will check if LC_ID starts with F & G then return
output
F04 | 1
else no record will be return.
You want to prioritize the values being returned. Because you want only one, you can do this with ORDER BY:
SELECT Top 1 LC_ID, COALESCE(LC_UD, 0) as Record
FROM CONTRACT
WHERE LC_ID LIKE '[FG]%'
ORDER BY (CASE WHEN LC_ID = 'F01' THEN 1 ELSE 2 END);
Note: This assumes you are using SQL Server (based on the syntax).
#gordon's answer is clever, though probably specific to Sql Server. Here's a different approach. The "Top 1" feature is also sql server, but could be avoided through additional techniques.
SELECT Top 1 LC_ID, ISNULL(LC_UD, 0) as Record
FROM CONTRACT
WHERE LC_ID = 'F01'
UNION
SELECT Top 1 LC_ID, ISNULL(LC_UD,0) As Record
FROM CONTRACT
WHERE NOT EXISTS (SELECT * FROM CONTRACT WHERE LC_ID = 'F01')
AND LC_ID LIKE '[FG]%'

Unable to remove duplicates with subquery

I had a built a query previously that returned zero duplicates until I decided to join in a couple more tables. Now that I've joined them in, I'm unable to create the desired flag due to duplicates being returned. I've attached the scenario below as an example.
I only want one occurrence of each reference number (123456789). I want to create a flag when certain criteria are met. For example, I want to see when reference numbers for a certain account meet "X", but when I join the table I get every instance of that reference number in the joined table.
REFNO BEG END STATUS
123456789 123 456 E
123456789 456 789 E
123456789 789 012 A
I want to see all of the REFNO's based on other parameters set in the query, but I want a flag for anything where END = '012'. I can't left join to the table because I will get all three lines. If I do an inner join then I just get the 012 lines. I Tried the code below in my select statement to only pull when that scenario exists, but I'm getting wacky returns and don't know why. I feel like this should be fairly easy to accomplish, but I can't wrap my head around how to create a flag for just that scenario without getting duplicates or removing results with an inner join.
,(CASE WHEN EXISTS(SELECT 1
FROM QW.ABCD Z
WHERE Z.ABCD = P.ABCD
AND Z.END = '012'
AND Z.TIMESTAMP IS NULL
AND Z.STATUS IN ('A','E'))
THEN 'Y' ELSE 'N'
END)
AS "FLAG"
Please help as I'm not sure what I'm doing wrong to get the flag I want to see.
I am not sure id DB2 allows this combination of UNION and GROUP BY, but what you want is probably something like this:
SELECT 'N' AS FLAG, REF_NO,MIN(BEG),MAX(THEEND) FROM TAB_QW A
WHERE NOT EXIST (SELECT * FROM TAB_QW B WHERE B.REF_NO = A.REF_NO AND B.THEEND = '012')
GROUP BY REF_NO
UNION
SELECT 'Y' AS FLAG, REF_NO,MIN(BEG),MAX(THEEND) FROM TAB_QW C
WHERE EXISTS (SELECT * FROM TAB_QW D WHERE D.REF_NO = C.REF_NO AND D.THEEND = '012')
GROUP BY REF_NO

How to prioritize in OR condition in SQL Server

I have a simple query where I want to search for a value in a column, and if no match is found then I want to discard that where condition and select any random value from that column.
I have tried to achieve this using OR condition, using case, but to no avail
select top 10 *
from tblRFCWorkload
where (f1 ='mbb' or f1 = f1)
In the above query I want the result table to have all rows with 'mbb', if 'mbb' is not found then give any value instead of mbb. But instead it returns only two rows with mbb even though there are 10 matching rows
select top 10 *
from tblRFCWorkload
where 1 = case when f1 = 'mbb' then 1 else 1 end
This query also returns the same result as the 1st query
If I change it to
select top 10 *
from tblRFCWorkload
where 1 = case when f1 = 'mbb' then 1 else 0 end
then it only rows having the mbb value.
Need similar thing with between clause... search for one range if no results found then search for second range... how do I do that???
I think you want something like this:
select top 10 *
from tblRFCWorkload
order by (case when f1 = 'mbb' then 1 else 2 end);
This prioritizes the rows that you want, fetching the top 10 which will be 'mbb', if they are available.
You want only the results where f1 = 'mbb' if there are any, otherwise nothing? In that case you need to be testing whether there are any matching rows. Something like this
SELECT TOP 10 *
FROM tblRFCWorkload
WHERE f1 = 'mbb' --the match you need
OR NOT EXISTS --or there are no matches
(SELECT * FROM tblRFCWorkload WHERE f1 = 'mbb')