How to prioritize in OR condition in SQL Server - sql

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')

Related

Max match same numbers from each row

To generate 1mln rows of report with the below mentioned script is taking almost 2 days so, really appreciate if somebody could help me with different script which the report can be generated within 10-15mins please.
The requirement of the report is as following;
Table “cover” contains 5mln rows & 6 columns of data and likewise table “data” contains 500,000 rows and 6 columns.
So, each numbers of the rows in table cover has to go through table date and provide the maximum matches.
For instance, as mentioned on the below tables, there could be 3 matches in row #1, 2 matches in row #2 and 5 matches in row #3 so the script has to select the max selection which is 5 in row #3.
Sample table
UPDATE public.cover_sheet AS fc
SET maxmatch = (SELECT MAX(tmp.mtch)
FROM (
SELECT (SELECT CASE WHEN fc.a=drwo.a THEN 1 ELSE 0 END) +
(SELECT CASE WHEN fc.b=drwo.b THEN 1 ELSE 0 END) +
(SELECT CASE WHEN fc.c=drwo.c THEN 1 ELSE 0 END) +
(SELECT CASE WHEN fc.d=drwo.d THEN 1 ELSE 0 END) +
(SELECT CASE WHEN fc.e=drwo.e THEN 1 ELSE 0 END) +
(SELECT CASE WHEN fc.f=drwo.f THEN 1 ELSE 0 END) AS mtch
FROM public.data AS drwo
) AS tmp)
WHERE fc.code>0;
SELECT *
FROM public.cover_sheet AS fc
WHERE fc.maxmatch>0;
As #a_horse_with_no_name mentioned in the comment to the question, your question is not clear...
Seems, you want to get the number of records which 6 fields from both tables are equal.
I'd suggest to:
reduce the number of select statements, then the speed of query execution will increase,
split your query into few smaller ones (good practice), to check your logic,
use join to get equal data, see: Visual Representation of SQL Joins
use subquery or cte to get result on which you'll be able to update table.
I think you want to get result as follow:
SELECT COUNT(*) mtch
FROM public.cover_sheet AS fc INNER JOIN public.data AS drwo ON
fc.a=drwo.a AND fc.b=drwo.b AND fc.c=drwo.c AND fc.d=drwo.d AND fc.e=drwo.e AND fc.f=drwo.f
If i'm not wrong and above query is correct, the time of execution of above query will reduce to about 1-2 minutes.
Finally, update query may look like:
WITH qry AS
(
-- proper select statement here
)
UPDATE public.cover_sheet AS fc
SET maxmatch = qry.<fieldname>
FROM qry
WHERE fc.code>0 AND fc.<key> = qry.<key>;
Note:
I do not see your data and i know nothing about its structure, relationships, etc. So, you have to change above query to your needs.

sql calculate column value then order by it

I have the sql below, and I then calculate one of the fields (market_cap) within the application code not the sql. I'd like to calculate it then order the records based on the top 7 calculated from it.
Proposed-ish Sql:
SELECT TOP 7 'market_cap' as [market_cap_calc] ??, [tradingcode],[last],[prvclose],[currentsharesonissue]
FROM [PricesCurrent]
ORDER BY tradingcode DESC
Asp code for field market_cap:
If Not IsNull(rs("last")) Then
marketcap = 0
If Not IsNull(rs("currentsharesonissue")) And Cdbl(rs("last")) <> 0 Then marketcap = (CDbl(rs("last")) * CDbl(rs("currentsharesonissue")))/1000000.0
End If
If marketcap = 0 And Not IsNull(rs("prvclose")) Then
If Not IsNull(rs("currentsharesonissue")) And CDbl(rs("prvclose")) > 0 Then marketcap = (CDbl(rs("prvclose")) * CDbl(rs("currentsharesonissue")))/1000000.0
End If
So basically it needs to check if last or prvclose is empty and then multiply either one by currentsharesonissue to get marketcap, and then get the top 7 rows based on that marketcap figure, how do I go about this? make a temporary table first?
You can do this with coalesce and a cte
WITH CTE AS(
SELECT
coalesce([last],[prvclose],0) * currentsharesonissue as CalculatedColumn
FROM [PricesCurrent])
select top 7 * from cte order by CalculatedColumn desc
COALESCE() is going to take the first NOT NULL value and multiply it by the currentsharesonissue column. Then, we just get the TOP7 as you stated, in DESCENDING order (assumed).

How to sort combination of integer and text in PostgreSQL?

I have this table
id value
1 OK
2 xminimum
3 NO
4 YES
I want to sort this table by value where minimum is always first then the rest according to alphabetic order of value column
Meaning:
xminimum
NO
OK
YES
I wrote this query:
Select *
from table_a
order by case when value='xminimum' then 1 else ????? end
I don't know what to put in the else... conceptually it should be else value end so it means alphabetic order.. but I can not combine integer with text.
How do I fix it?
As requested, copied from my comment:
Select *
from table_a
order by case when value='xminimum' then 1 else 2 end, value
Another solution:
SELECT *
FROM table_a
ORDER BY value <> 'xminimum', value;
Do it like you have and add the value column as second column to sort by:
SELECT *
FROM table_a
ORDER BY CASE WHEN value='xminimum' THEN 1 ELSE 2 END, value

The MIN() Function Ms Access

this is a sample sql query that i created ms access query. i am trying to get only one row the min(DATE). how ever when i run my query i get multiple lines. any hits? thanks
SELECT tblWarehouseItem.whiItemName,
tblWarehouseItem.whiQty,
tblWarehouseItem.whiPrice,
Min(tblWarehouseItem.whiDateIn) AS MinOfwhiDateIn,
tblWarehouseItem.whiExpiryDate,
tblWarehouseItem.whiwrhID
FROM tblWarehouseItem
GROUP BY tblWarehouseItem.whiDateIn,
tblWarehouseItem.whiItemName,
tblWarehouseItem.whiQty,
tblWarehouseItem.whiPrice,
tblWarehouseItem.whiExpiryDate,
tblWarehouseItem.whiwrhID;
If i have my sql code like that is working as it should:
SELECT MIN(tblWarehouseItem.whiDateIn) FROM tblWarehouseItem;
In the first query, you group by a number of columns. That means the minimum value will be calculated for each group, which in turn means you may have multiple rows. On the other hand, the second query will only get the minimum value for the specified column from all rows, so that there is only one row in the result set.
A simple example is shown below to illustrate the above.
Table:
Key Value
1 1
1 2
2 3
2 4
On Group By Key:
GroupKey MinValue
1 = min(1,2) = 1 -> Row 1
2 = min(3,4) = 3 -> Row 2
On Min (Value)
MinValue
=min(1,2,3,4) = 1 -> Row 1
For a table like above, if you want to select all rows and also show the minimum value from whole table rather than per group, you can do something like this:
select key, (select min(value) from table)
from table
SELECT WI.*
FROM tblWarehouseItem AS WI INNER JOIN (SELECT whiimtID, MIN(tblWarehouseItem.whiDateIn) AS whiDateIn
FROM tblWarehouseItem
GROUP BY whiimtID) AS MinWI ON (WI.whiDateIn = MinWI.whiDateIn) AND (WI.whiimtID = MinWI.whiimtID);

Where clause based on priority

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.