SQL Server, using or statement condition - sql

I am using a query which its searching inside a table for two conditions. I will give an example:
Select *
from Customers
where mobile= '" + textboxt1.Text + "' or Phone = '" + textboxt1.Text + "'
The query returns me the first row which mobile or phone numbers is equal with my textbox1.Text.
I need to set a condition: start looking "entire table" for find the first 'or' statement(mobile). If there is not exist any result then go and search again entire table using the second or condition (Phone).
Is there any easy way which i can write my query? Or do I need to use a case for this?

Assuming that not more than one record in the table would match on mobile, and that not more than one record would match on the phone (which seems relevant given your description of your use case), you could use top 1 and conditional ordering:
select top 1 *
from Customers
where mobile= #textboxt1 or phone = #textboxt2
order by case when mobile= #textboxt1 then 0 else 1 end
If a record matches on mobile, the conditional ordering clause will put it in first position, and top 1 will eliminate the (possible) other record matching on phone. Else, the (only) matching record on phone will be retained.
Note: don't trust user input. Use prepared statement and query parameters at all times. I modified the query so it uses parameters (#textboxt1, #textboxt2).

You can sometimes improve performance by choosing a UNION instead of an OR.
SELECT TOP 1 * FROM (
SELECT *, 0 Ordinal
FROM Customers
WHERE mobile = #number
UNION ALL
SELECT *, 1 Ordinal
FROM Customers
WHERE phone = #number
) t
ORDER BY Ordinal

Related

Subquery with GROUPBY on calculated field: Your query does not include the specified expression '' as part of an aggregate function

I get the following error message
"Your query does not include the specified expression 'SampleCode' as part of an aggregate function."
I've looked into aggregate functions and have tried various ways to GROUP BY using the individual data fields that make up the code but I can't seem to get anything to work.
'SampleCode' is a concatenated query field (query name: datqry_SampleNumber) that is based on data from 3 different tables to create a unique value as follows...
SampleCode: IIf([tbl_Carcass.SampleNumber]="-999","-999",
"NPT-" & [tbl_SurveyInfo.SurveyYear*] & "-" &
[datqry_TransectData.Project_Code] & "-" & [tbl_Carcass.SampleNumber])
for SampleNumber values > 0001 (-999 is a placeholder indicating no SampleNumber assigned). Note, SurveyYear* is a calculated field based on the SurveyDate data field.
So, since SampleCode needs to be unique to each sample, I am trying to build a duplicate query, based on the aforementioned query, to identify duplicate SampleCodes so they can be relabeled and archived w/ a unique qualifier. The criteria for the duplicate query operation is as follows
In (SELECT [SampleCode] FROM [datqry_SampleNumber] As Tmp
GROUP BY [SampleCode] HAVING Count(*)>1 )
Any ideas on how to tackle this problem? Thank you in advance for your help and suggestions.
This looks like it might be a limitation of the JET engine used by Access to interpret its SQL.
It appears to be having trouble working with the subquery because it contains an aggregation of a calculated field (SampleCode in your case).
Try saving this as a separate query called, e.g. qryDuplicates:
SELECT [SampleCode] FROM [datqry_SampleNumber]
GROUP BY [SampleCode] HAVING Count(*)>1;
Then what you are trying to do will work as expected:
SELECT * from someTable WHERE someField IN (
SELECT * FROM qryDuplicates
);
TECHNICAL NOTE: I've tested it out and it is indeed specific to the fact that SampleCode is a calculated field. Doing exactly the same kind of grouped subquery works as expected when the field in question is not calculated.
With this test database this query works:
SELECT * FROM Table2 WHERE Field3 IN (
SELECT Field1 FROM datqry_SampleNumber
GROUP BY Field1 HAVING COUNT(*) > 1
);
And this doesn't
SELECT * FROM Table2 WHERE Field3 IN (
SELECT SampleCode FROM datqry_SampleNumber
GROUP BY SampleCode HAVING COUNT(*) > 1
);

sql server - how to execute the second half of 'or' clause only when first one fails

Suppose I have a table with following records
value text
company/about about Us
company company
company/contactus company contact
I have a very simple query in sql server as below. I am having problem with the 'or' condition. In below query, I am trying to find text for value 'company/about'. If it is not found, then only I want to run the other side of 'or'. The below query returns two records as below
value text
company/about about Us
company company
Query
select
*
from
tbl
where
value='company/about' or
value=substring('company/about',0,charindex('/','company/about'))
How can I modify the query so the result set looks like
value text
company/about about Us
A bit roundabout, but you can check for the existence of results from the first where clause:
select
*
from
tbl
where
value='company/about' or
(
not exists (select * from tbl where value='company/about')
and
value=substring('company/about',0,charindex('/','company/about'))
)
Since your second condition can be re-written as value = 'company' this would work (at least for the data and query you've presented):
select top(1) [value], [text]
from dbo.MyTable
where value in ('company/about', 'company')
order by len(value) desc
The TOP() ignores the second row if both are found, and the ORDER BY ensures that the first row is always the one with 'company/about', if it exists.

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 = '*'

How do you query an int column for any value?

How can you query a column for any value in that column? (ie. How do I build a dynamic where clause that can either filter the value, or not.)
I want to be able to query for either a specific value, or not. For instance, I might want the value to be 1, but I might want it to be any number.
Is there a way to use a wild card (like "*"), to match any value, so that it can be dynamically inserted where I want no filter?
For instance:
select int_col from table where int_col = 1 // Query for a specific value
select int_col from table where int_col = * // Query for any value
The reason why I do not want to use 2 separate SQL statements is because I am using this as a SQL Data Source, which can only have 1 select statement.
Sometimes I would query for actual value (like 1, 2...) so I can't not have a condition either.
I take it you want some dynamic behavior on your WHERE clause, without having to dynamically build your WHERE clause.
With a single parameter, you can use ISNULL (or COALESCE) like this:
SELECT * FROM Table WHERE ID = ISNULL(#id, ID)
which allows a NULL parameter to match all. Some prefer the longer but more explicit:
SELECT * FROM Table WHERE (#id IS NULL) OR (ID = #id)
A simple answer would be use: IS NOT NULL. But if you are asking for say 123* for numbers like 123456 or 1234 or 1237 then the you could convert it to a varchar and then test against using standard wild cards.
In your where clause: cast(myIntColumn as varchar(15)) like '123%'.
Assuming the value you're filtering on is a parameter in a stored procedure, or contained in a variable called #Value, you can do it like this:
select * from table where #Value is null or intCol = #Value
If #Value is null then the or part of the clause is ignored, so the query won't filter on intCol.
The equivalent of wildcards for numbers are the comparators.
So, if you wanted to find all positive integers:
select int_col from table where int_col > 0
any numbers between a hundred and a thousand:
select int_col from table where int_col BETWEEN 100 AND 1000
and so on.
I don't quite understand what you're asking. I think you should use two different queries for the different situations you have.
When you're not looking for a specific value:
SELECT * FROM table
When you are looking for a specific value:
SELECT * FROM table WHERE intcol = 1
You can use the parameter as a wildcard by assigning special meaning to NULL:
DECLARE #q INT = 1
SELECT * FROM table WHERE IntegerColumn = #q OR #q IS NULL
This way, when you pass in NULL; you get all rows.
If NULL is a valid value to query for, then you need to use two parameters.
If you really want the value of your column for all rows on the table you can simply use
select int_col
from table
If you want to know all the distinct values, but don't care how many times they're repeated you can use
select distinct int_col
from table
And if you want to know all the distinct values and how many times they each appear, use
select int_col, count(*)
from table
group by int_col
To have the values sorted properly you can add
order by int_col
to all the queries above.
Share and enjoy.

How do I select only 1 row in sybase without using rowcount

How do I select only 1 row in sybase without using rowcount? I don't have the privilege to set rowcount in sybase. Is there a way to select only 1 row?
For example:
select * from table where name = 'jack'
This returns two rows; how do I select only one row from the result set without using set rowcount?
Try the query:
SELECT TOP 1 * FROM mytable
WHERE name = 'jack'
As you might guess, this selects the TOP 1 matching results. If you wanted more (which you don't here) you could use any number (TOP 100 or TOP 1000, etc).
A more comprehensive example can be found on w3schools: http://www.w3schools.com/Sql/sql_top.asp
There seems to be a reason, why you're getting more than 1 row for "WHERE name = 'jack'", it looks as if the rows differ.
But if, the rows do not differ you can try adding "distinct":
SELECT DISTINCT * FROM TABLE WHERE name = 'jack'
or try with "GROUP BY" statement, then you should type explicitly all columns, eg.:
SELECT name FROM TABLE WHERE name = 'jack' GROUP BY name
if this is not what you wanted, can you paste here how the 2 rows look exactly?
If you want a single result, use 'GROUP BY' and 'HAVING column = max(column)'. Or replace max() with min().
This should work unless the max or min values are also not unique.