Get the result of the first condition in the query - sql

I want to make a query that searches the table for names of cities and that the result will be names of cities that start with the letter b and then names of cities that contain the letter b.
select *
from tb_city
where name like 'b%' or name like '%b%'
How can I first get the cities that start with the letter b and then the cities that contain the letter b?
The result I get is mixed

you need to use union all for this.
select *
from tb_city
where name like 'b%'
union all
select *
from tb_city
where name like '%b%' and name not like 'b%'

For conditional logic where you want to inspect and sort by the results of individual constraints you can use UNION, but you will need to add a discriminator or sort indicator column to identify the difference between the result sets. Note that this will however result in duplicate rows unless you deliberately exclude the 'b%' from the '%b%' result sets:
SELECT *, SortOrder = 0
FROM tb_city
WHERE name LIKE 'b%'
UNION ALL
SELECT *, SortOrder = 1
FROM tb_city
WHERE name like '%b%' and name NOT LIKE 'b%'
ORDER BY SortOrder
NOTE: only the last SELECT in the set can have the ORDER BY clause, the order is evaluated after the result sets are combined
An alternate solution that works well form multiple criteria, is to use a case statement to determine the sort. Using CASE will make it easier to ensure that you only get 1 of each record, without having to write the criteria as a mutually exclusive set:
SELECT *
FROM tb_city
WHERE name LIKE 'b%' or name LIKE '%b%'
ORDER BY CASE
WHEN name LIKE 'b%' THEN 0
WHEN name LIKE '%b%' THEN 1
ELSE 2
END
NOTE: It is good practise to specify a default constraint in your case statements, especially when using this conditional expression for sorting. If your WHERE criteria becomes out of sync with the CASE it might result in additional rows in the results, if no ELSE is specified then the extra rows will have a value of NULL, in SQL Server that will mean they will be sorted before the 0s. (In other RDBMS this behaviour is configurable and the defaults may not be what you expect...)
Remove any ambiguity be being explicit with your sorting and make sure you cover all bases.
The problem with a resultset like this that uses CASE directly in the ORDER BY though can be that it is hard to visualise why the results are rendered in that order, it can be hard to confirm the sequence logic.
If you want to debug the sorting criteria or just need to know why the data is sorted in a specific way, you can moe the CASE out to an expression based column in the set, like the UNION solution, we add in the discriminator column:
SELECT *
, CASE
WHEN name LIKE 'b%' THEN 0
WHEN name LIKE '%b%' THEN 1
ELSE 2
END as SortOrder
FROM tb_city
WHERE name LIKE 'b%' or name LIKE '%b%'
ORDER BY SortOrder
There is no significant performance difference between this and the previous query other than the additional bytes over the wire, by referencing the alias of the SortOrder expression the expression will not be re-evaluated.

Related

SQL - Where clause with case statement and wildcards

I'm working in Oracle's APEX environment, trying to return all values in one case and specific values in another case. If you aren't familiar with APEX, it uses low-code to produce a front-end page that is data driven; this case uses a dropdown to select from a list, and I'm comparing that list selection to values pulled from my database.
This creates the dropdown list (requires 2 columns - a display column [name], and a return column [id]):
select distinct 'All users' as name,
'99999' as id
from real_table
union
select distinct name,
id
from real_table
That input is stored in a variable we'll call :LIST_INPUT. I want to select all values from another_table when 'All users' is selected, and only those associated with the particular user when their name/id is selected. Below is the code I have to try and achieve that, but no dice.
select name,
id,
other_col1,
other_col2
from another_table
where case
when :LIST_INPUT like '99999' then '%'
else :LIST_INPUT
end like id
This works fine when a real user id is selected, but returns nothing when the 'All users' value is selected. My logic here is that I'm asking it to compare a wildcard to the ID field, so it should return everything, but instead it returns nothing.
Thanks!
Probably case statement is not necesasary, look:
select name,
id,
other_col1,
other_col2
from another_table
where id = :LIST_INPUT
OR :LIST_INPUT like '99999' -- You can use any other condition here
I think your LIKE operator has the operands in the wrong order. Shouldn't it be?
select name,
id,
other_col1,
other_col2
from another_table
where id like case
when :LIST_INPUT like '99999' then '%'
else :LIST_INPUT
end

CASE WHERE change operator - TSQL

I was wondering if you could do a case statement in the WHERE clause which changes the operator.
What I am trying to do is filter out results based on a boolean value.
SELECT *
FROM table1
WHERE
CASE #Status
WHEN 1 THEN Name LIKE 'SOMETHING%'
WHEN 2 THEN Name NOT LIKE 'SOMETHING%'
END
I was wondering if this is possible?
You can do it without a SWITCH expression, like this:
SELECT *
FROM table1
WHERE
(#Status = 1 AND Name LIKE 'SOMETHING%')
OR (#Status = 2 AND Name NOT LIKE 'SOMETHING%')
Since #Status can be equal to only one thing at a time, only one component of the OR expression would determine the outcome of the WHERE condition.

Completing a given SQL statement so that another column is displayed in the end

I'm given the following statement:
SELECT id FROM record_database WHERE id = <up to me to complete the statement>
The record database has different fields, among which are id and name.
I'm supposed to complete this select statement so that it displays all the ids and all the corresponding names side by side, and this should be done using this one line of SQL code. A hint was given that UNION or OR can be used.
I tried variations of the following:
SELECT id FROM record_database WHERE id = '*'
UNION
SELECT name FROM record_database WHERE name = '*';
But none of these worked. I tried doing this with AND, tried using display columns, but those didn't work either.
Any help would be appreciated.
This smells a great deal like homework, so I won't offer a complete answer, but you can't just union queries that return dissimilar result sets. I'm inferring that ID is an integer while NAME is some varchar, which won't union as you've listed in your hint.
When you say "complete," are you restricted to adding things to the end? If so, its a non-starter. You can't increase the list of fields being returned merely by adding things to the "WHERE" clause. You need to add things to the actual field list to get them to be returned, so you might clarify whether you are truly restricted to appending to the query you;ve given.
If you are looking for:
id
name
id next
name next
Then use this trick:
SELECT col2
FROM (
SELECT id, col2=convert ( varchar (size of name field),id)
FROM table
WHERE ....
UNION ALL
SELECT id, name
FROM table
WHERE ....
)
ORDER BY id
This order by will bring id and name side by side and col2 will contain id in first row and name in second row.
Cheating. Make the select return 0 rows and add another one that will show 2 columns. All in one and the same line:
SELECT id FROM record_database WHERE id = NULL;SELECT id,name FROM record_database;
No more time should be wasted on silly problems like this.
If both id and name are char (or varchar), you could also do this, concatting the two columns into one:
SELECT id FROM record_database WHERE id = NULL
UNION ALL
SELECT id || '--' || name FROM record_database ;
The id || '--' || name part differs from one DBMS to another. In some, the + is the concat operator, in others there are special functions. So you may need to use:
id + '--' + name
or:
CONCAT(id, '--', name)
Try this
SELECT * FROM record_database WHERE id = '*' OR name = '*'

ordering by match accuracy in t-sql using multiple where-like statements

I am building a query such as this:
SELECT * FROM mytable
WHERE field like '%a%'
OR field like '%b%'
OR field like '%c'
I'd like to tag on an ORDER BY clause that orders by the amount of matches found--something along the lines of making some extra column in the result set that increments if a, b or c was found in the field and then order by that number.
is this possible without creating some kind of temp table?
You probably want to look into full text indexing if this table is at all large but a query without.
SELECT *
FROM mytable
WHERE field like '%a%'
OR field like '%b%'
OR field like '%c'
ORDER BY CASE
WHEN field like '%a%' THEN 1
ELSE 0
END + CASE
WHEN field like '%b%' THEN 1
ELSE 0
END + CASE
WHEN field like '%c%' THEN 1
ELSE 0
END

Sql Server Full Text Search Single Result Column Searched Across Multiple Columns

I am trying to implement an AutoComplete search box(like google) using SQL Server 2008 and Full Text Search.
Say I have 3 columns that I want to search across and have created the proper indexes and what not.
The columns are ProductName, ProductNumber, and Color...
For the user input I want to search for possible matches across all three columns and suggest the proper search term.
So say the user starts typing "Bl"
id like to return a single column containtng results like "Black" "Blue" which come from the Color column and also any matches from the other two columns(like ProductNumber: BL2300)
So basically I need to search across multiple columns and return a single column as the result. Is there a way to do this?
UPDATED follwoing comment of op If you created a FULLTEXT INDEX on different columns, then you can simple use CONTAINS or FREETEXT to look on one of them, all of them, or some of them. Like this:
SELECT *
FROM YourTable
WHERE CONTAINS(*, #SearchTerm);
If you want to look on all the columns that are included in the FULLTEXT INDEX. or:
SELECT *
FROM YourTable
WHERE CONTAINS((ProductName, ProductNumber, Color), #SearchTerm);
If you want to specify the columns that you want to search.
If you need the results in one column, you are gonna have to do a UNION and do a search for every column you want to be searched.
SELECT *
FROM YourTable
WHERE CONTAINS(ProductName, #SearchTerm)
UNION
SELECT *
FROM YourTable
WHERE CONTAINS(ProductNumber, #SearchTerm)
UNION
SELECT *
FROM YourTable
WHERE CONTAINS(Color, #SearchTerm)
If you do not need to associate the single columns, something like
SELECT * FROM Table WHERE ProductName LIKE #SearchTerm + '%'
UNION
SELECT * FROM Table WHERE ProductNumber LIKE #SearchTerm + '%'
UNION
SELECT * FROM Table WHERE Color LIKE #SearchTerm + '%'
is a good point to start from.