Create a SQL select query dynamically at runtime - sql

I have a requirement where I need to write a SQL select query with dynamic columns at runtime. There are few mandatory and optional fields in the DB. I want to generate the query at runtime based on the values present in the incoming request.
Ex: DB has colms A,B,C,D,E
scenario 1: request has only value for A, query should be generated as
select * from table where A='<somevalue>'
scenario 2 . Request has value for A and D , query should be generated as
select * from table where A='<somevalue>' and D='<somevalue>'
Currently it is being handled using java to create string for not null values and appending it to select statement to form the final query.
Ex:
if (A!=null)
String query_a='<somevalue>'
else
query_a=""
and then appending <query_a> <query_b> to form final query
Is there a better way to achieve this?

In your SQL script, you can better parametrize like below. I've assume that you are using parameters.
**It's basically sql idea.
SELECT *
FROM table
WHERE (
(#p1 IS NULL OR columnA = #p1)
OR (#p2 IS NULL OR columnB = #p2)
OR (#p3 IS NULL OR columnC = #p3)
OR (#p4 IS NULL OR columnD = #p4)
)

You may want to consider doing this construction of queries in Java, creating an appropriate Prepared Statement for each case.
List<String> clauses = new ArrayList<String>();
List<String> params = new ArrayList<String>();
clauses.add("1=1");
if (you_want_to_search_on_column_a) {
clauses.Add("column_a = ?");
params.Add(value_to_search_on_column_a);
}
if (you_want_to_search_on_column_b) {
clauses.Add("column_b = ?");
params.Add(value_to_search_on_column_b);
}
String queryString = "SELECT * FROM table WHERE " + String.join(" AND ", clauses);
PreparedStatement stmt = con.prepareStatement(queryString);
for (int i = 0; i < params.size; i++ ) {
stmt.setString(i+1, params.get(i));
}
ResultSet rs = stmt.executeQuery();
This way you'll present queries with exactly the filtering criteria you need, and so give MySQL's query planner the best possible shot at optimizing each one.
If you were working with Oracle or SQL server it would be worth your trouble to keep a cache of PreparedStatement objects, but that's not so with MySQL.

Related

How can I run the SQL like "SELECT * from table where columnA = columnB;" in Parse API?

In Parse, I am using REST API to retrieve some results from a table.
I would like to select a row where the value of one column is equal to another column. i.e. I would like to send the SQL like
SELECT * from table where columnA = columnB;
there's a document here ( http://parse.com/docs/rest/guide ) and it shows how to send the query like
SELECT * from table where columnA = 'some value';
but it doesn't say how to send what I want to. I have tried a couple of ways which I thought would do but never succeded.

How can I insert new rows and delete missing rows from a table given a collection of values?

Lets say I have a table with the following data.
Id Value
1 | A
2 | B
3 | C
I need to synchronize the values in this table with a collection of values. I would like to remove any rows which are not in my collection, add rows which are and leave the matching ones alone.
Given this collection of values:
C,D,E
After the operation I expect the table to contain:
Id Value
3 | C
4 | D
5 | E
I'm aware of most of the obvious solutions which require multiple queries. What I'm looking for are possible solutions that are more efficient. Can I use the MERGE statement here somehow?
Edit - The collection values are in a C# collection (List<string>) and I am using the standard SqlConnection/SqlCommand in .NET to execute the query.
Here's something I considered to take care of removing values. But this might be frowned upon because I would have to do a bit of string concatenation to create it.
DELETE FROM [MyTable]
WHERE [Value] NOT IN ('C','D','E')
But then to add values it seems like I would have to create multiple IF NOT EXISTS THEN INSERT query statements for each value in my collection.
I don't think you can do this in a single SQL statement, but you could create a stored procedure to do the job:
create procedure upsertnewrecords(
#collection varchar(max)
) as
begin
delete
from yourtable
where charindex(','+value+',', ','+#collection+',') = 0
;with cte as (
select split.t.value('.', 'VARCHAR(100)') newvalue
from (
select cast ('<M>' + replace(#collection, ',', '</M><M>') + '</M>' as xml) as String
) t
cross apply String.nodes ('/M') AS Split(t)
)
insert into yourtable
select newvalue
from cte
where newvalue not in
(select value from yourtable)
end
SQL Fiddle Demo
This stored procedure first uses CHARINDEX to delete values that aren't in your current list, then uses CROSS APPLY to convert your comma delimited list to a table-valued list and finally insert those via a common table expression.
Okay, so your collection is in a C# list. That makes this easier. This isn't the most efficient way to do it since it involves a lot of queries, and it would work better using a Dictionary, but it's a solution if you aren't pressed for time and don't want to use string concatenation to make a complicated query.
using (SqlConnection connection = new SqlConnection(.....))
{
connection.Open;
using (SqlCommand command = new SqlCommand("SELECT ID, Value FROM Table"))
{
using (SqlDataReader reader = SqlCommand.ExecuteReader())
{
while (reader.Read())
{
if (THELIST.Contains(reader["Value"].ToString())
{
THELIST.Remove(reader["Value"].ToString());
}
else
{
//Execute a SqlCommand in here to do a DELETE where ID = reader["ID"]
}
}
}
}
//Now that you've deleted all the ones that aren't in this list, go through what's left in the list and insert them (only the ones that aren't in the database will be left, since you deleted them as they were found
foreach (string thing in THELIST)
{
//Execute a SqlCommand to do an insert into the database
}
}

How to make this query faster?

My Db look like this:
id | Column1 | Column2
Must known facts: id is not a primary unique id (but could be). id can go up to 2Millions+. Column values are filled with TINYINT
var query : String = "SELECT Column1 FROM Table1 WHERE Column1 <> 0";
dbcmd = dbcon.CreateCommand();
dbcmd.CommandText = query;
reader = dbcmd.ExecuteReader();
var result : int = 0;
while(reader.Read()) {
result++;
}
return result;
But for a basic search it makes up to 5 seconds, is there anyway to make it faster?
Edit: Like always, thanks for the contributors and the rapidity!
Yes, you are reading your results and processing them one by one. All you seem to be doing to need is the count, which you can get with:
"SELECT COUNT(*) FROM Table1 WHERE Column1 <> 0";
This doesn't look like javascript code, but you could try counting the records instead of executing the query and then looping through the entire resultset on the client and increment a variable:
var query : String = "SELECT Count(Column1) FROM Table1 WHERE Column1 <> 0";
This will be much faster than your code because the count operation will be done by the database server directly.
Yes, index the table on Column1, the row used in the where clause.

SQL: Best way to write a condition that checks the value of a variable when the variable could be null

I am writing a pgplsql function in which I have a variable var that could be NULL or valorized. In a later query I do:
SELECT * FROM table WHERE column = var
that, in case of a NULL var, becomes
SELECT * FROM table WHERE column = NULL
So the query fails with NULL, because, as PostgreSQL documentation says,
The null value represents an unknown value, and it is not known whether two unknown values are equal
I resolved it with a CASE statement:
SELECT * FROM table WHERE
( CASE WHEN var IS NULL THEN column IS NULL ELSE column = var END ) = TRUE
But I am unsure wether this is the best way to resolve the question... do you have any good alternative?
SELECT * FROM table WHERE column IS NOT DISTINCT FROM var
If var has a value of NULL, do you really only want to select records having a column value of NULL? Or would you want to treat it as a 'select all'/'do not restrict'?
If the latter applies, then an approach like this would work. (This is pseudocode as I am native to MSSQL.)
SELECT * FROM table WHERE
(var IS NULL AND column = column) OR column = var

SQL: Where MYID = ANY?

In a SQL query, that contains
... WHERE MYID = #1 ....
I have to manage 2 cases
1) There is a filter on a column, #1 will be a number (1,2,X...)
2) There is no filter on that column, #1 will be ...? (ANY)
Is there something for this "any" (SQL Server 2005) ?
PS.
Obviously, I understand that I can remove the "where".
PPS.
I explain myself for better understanding: I have this query in the code, and would like to pass an integer as parameter when the filter is ON, and "something" when my filter is OFF.
if (filterOn)
GetFoos(fooID);
else
GetFoos("ANY");
GetFoos(param1): "select * from FOOS where FOOID = {0}", param1
Make a UNION ALL of the two statements:
SELECT *
FROM mytable
WHERE myid = #col
UNION ALL
SELECT *
FROM mytable
WHERE #col IS NULL
or just split them in an IF / ELSE block of a stored procedures.
Either way, the optimizer will be able to optimize the queries separately, completely ignoring one of them depending on the value of #col.
you could do something along this line:
where (myid = #id or #id is null)
so you will only filter when #id contains a value and not when it is null.
Just remove the where or and clause if there is no filter on that column.
If you don't want to filter on a particular column, just don't filter on that column. Remove the WHERE MYID = entirely
Having
"select * from FOO where FOOID = {0}", param
use param="FOOID" when there is no param to filter, this will give
select * from FOO where FOOID = FOOID // removing the filter