Order by instr in Oracle - sql

I need to order a query in a particular way according to search criteria. I have the ordering of the search working for db2 but I also need to get it working for Oracle.
My query for db2 uses the locate function.
Select *
from <table>
where UPPER(NAME) like "'%<search>%'
order by locate('<search>', UPPER(NAME)),
UPPER(NAME)
This would return a search of review as:
Review,
Review A Task,
Review B Task,
Another Review
I have tried to use the instr function in oracle but it is not returning what I had hoped.
select *
from <table>
where UPPER(name) like '%<search>%'
order by instr('<search>',UPPER(name)),
name
Any ideas on what I need to do to get the order I am looking for?

You have the parameters in the instr the wrong way round. You are currently looking for the pattern UPPER(nane) inside the search term. The following works for me:
with sample_data as (select 'Review' name from dual union all
select 'Review A Task' name from dual union all
select 'Review B Task' name from dual union all
select 'Another Review' name from dual)
select *
from sample_data
where UPPER(name) like '%REVIEW%'
order by instr(UPPER(name), 'REVIEW'),
name;
NAME
--------------
Review
Review A Task
Review B Task
Another Review

Related

Find out what pattern was matched when using a LIKE query?

If I was to perform a normal query with a bunch of LIKE statements in it. Would it be possible to return which search term actually resulted in the row being returned?
So if I ran :
select cand_id
FROM cand_kw
WHERE client_id='client'
AND ( ( UPPER(kw) LIKE '%ANDREW%' AND UPPER(kw) LIKE '%POSTINGS%' )
OR ( UPPER(kw) LIKE '%BRET%' )
OR ( UPPER(kw) LIKE '%TIM%' )) ) )
And it returned some rows of results is there a way to tag on which term was actually matched in the row? So if '%ANDREW%' was what caused this row to be returned I could then show that information.
The data base engine is oracle 9i and I realize that this is normally a function something like full text searches that this database is not setup to handle so I am just trying to fake it in way.
It is a bit tricky, because more than one keyword may match. You could use a CASE expression in the SELECT clause, but then you would get the first matching keyword only.
Another approach would be to put each keyword on a separate row, use a join to filter the original table, and then aggregate the list of matching keyword.
So:
SELECT c.cand_id, LISTAGG(k.kw, ', ') WITHIN GROUP (ORDER BY k.kw) matches
FROM cand_kw c
INNER JOIN (
SELECT 'ANDREW' kw FROM DUAL
UNION ALL SELECT 'POSTINGS' FROM DUAL
UNION ALL SELECT 'BRET' FROM DUAL
UNION ALL SELECT 'TIM' FROM DUAL
) k ON c.kw LIKE '%' || k.kw || '%'
GROUP BY c.cand_id

Adding a column to pull in name of the table in union query

I have 2 queries that I want to combine before exporting to Excel. I used a UNION query to do so, which worked great. Now I want to create a column that says the name of the table it came from. What would be the best way to do this? In the 2 separate queries or the joined query?
For reference:
SELECT qry_xxx.Sold_Date, qry_xxx.Sold_Year, qry_xxx.Sold_Month
FROM qry_xxx
UNION SELECT qry_yyy.Sold_Date, qry_yyy.Sold_Year, qry_yyy.Sold_Month
FROM qry_yyy;
Please try the query below:
SELECT qry_xxx.Sold_Date, qry_xxx.Sold_Year, qry_xxx.Sold_Month, 'qry_xxx' as NameOfTable
FROM qry_xxx
UNION
SELECT qry_yyy.Sold_Date, qry_yyy.Sold_Year, qry_yyy.Sold_Month, 'qry_yyy' as NameOfTable
FROM qry_yyy;
EDIT:
You can use "group by" after using your first query as a subquery like below:
Select max(Sold_Date) as MaxSoldDate,
max(Sold_Year) as MaxSoldYear,
max(Sold_month) as MaxSoldMonth,
NameOfTable
FROM (
SELECT qry_xxx.Sold_Date, qry_xxx.Sold_Year, qry_xxx.Sold_Month, 'qry_xxx' as NameOfTable
FROM qry_xxx
UNION
SELECT qry_yyy.Sold_Date, qry_yyy.Sold_Year, qry_yyy.Sold_Month, 'qry_yyy' as NameOfTable
FROM qry_yyy;
) x
group by NameOfTable
I am guessing that you do not need to remove duplicates. If so, you should use union all and not union.
Then, just add the table name as a string column:
SELECT 'qry_xxx' as which, qry_xxx.Sold_Date, qry_xxx.Sold_Year, qry_xxx.Sold_Month
FROM qry_xxx
UNION ALL
SELECT 'qry_yyy' as which qry_yyy.Sold_Date, qry_yyy.Sold_Year, qry_yyy.Sold_Month
FROM qry_yyy;

select TableData where ColumnData start with list of strings

Following is the query to select column data from table, where column data starts with a OR b OR c. But the answer i am looking for is to Select data which starts with List of Strings.
SELECT * FROM Table WHERE Name LIKE '[abc]%'
But i want something like
SELECT * FROM Table WHERE Name LIKE '[ab,ac,ad,ae]%'
Can anybody suggest what is the best way of selecting column data which starts with list of String, I don't want to use OR operator, List of strings specifically.
The most general solution you would have to use is this:
SELECT *
FROM Table
WHERE Name LIKE 'ab%' OR Name LIKE 'ac%' OR Name LIKE 'ad%' OR Name LIKE 'ae%';
However, certain databases offer some regex support which you might be able to use. For example, in SQL Server you could write:
SELECT *
FROM Table
WHERE NAME LIKE 'a[bcde]%';
MySQL has a REGEXP operator which supports regex LIKE operations, and you could write:
SELECT *
FROM Table
WHERE NAME REGEXP '^a[bcde]';
Oracle and Postgres also have regex like support.
To add to Tim's answer, another approach could be to join your table with a sub-query of those values:
SELECT *
FROM mytable t
JOIN (SELECT 'ab' AS value
UNION ALL
SELECT 'ac'
UNION ALL
SELECT 'ad'
UNION ALL
SELECT 'ae') v ON t.vame LIKE v.value || '%'

Ordering in SQL while using logical operators

I'm trying to write an SQL query that has "OR" operator. The thing is that I want it to work with some, let say "priorities". I have an entity Item, it has two fields that I use in search:
description
title
And there is an SQL query:
select * from item
where description like '%a%' or title like '%a%';
What I want here is that if we have two entities returned and one of them matches like '%a%' by description and another one - by title, the one that matches via title should be the first one in the list. In other words, it should have bigger priority. Is there a way I can describe such a purpose in SQL?
Dialect: Oracle / H2
In Oracle, you may use a CASE to order by a values that makes rows ordered by the way they match your conditions:
/* test case */
with item(title, description) as (
select '__x__', '__x__' from dual union all
select '__x__', '__a__' from dual union all
select '__a__', '__x__' from dual union all
select '__a__', '__a__' from dual
)
/* the query */
select *
from item
where description like '%a%' or title like '%a%'
order by case
when title like '%a%'
then 1
else 2
end
This gives:
TITLE DESCR
----- -----
__a__ __x__
__a__ __a__
__x__ __a__

add a none existing result to SQL

So i have a quite strange need. I have to add none existing record to outcome of select query. Why? Query is a source of dropdown options in my Access application and i want to add one other option that is not in any table (as a form of default).
So now i have simple:
SELECT rowName FROM verySpecialTable
and i want to have
(SELECT rowName FROM verySpecialTable) + "default"
Can i do it by SQL? or do i have to add dummy record to verySpecialTable
You can use a UNION to the Dual table.
SELECT rowName FROM verySpecialTable
UNION
SELECT 'default' AS rowName FROM Dual
Since the Dual table might not exist in your access instance, you can emulate it as explained here: Table-less UNION query in MS Access (Jet/ACE)
or you can use existing table itself
SELECT rowName FROM verySpecialTable
UNION
SELECT top 1 'default' AS rowName FROM verySpecialTable