I need to use the IN clause in the SQL sentence.
I have data in one table with the type on Int(11).
And Y have a String from another table that is the criteria.
For example, in table A i have the value 3 of type Int.
In table/process B i have the String "0123".
I need to query table A to meet this criteria:
Select * from Table A where attrib_1 IN (0,1,2,3)
Because record n have value 3, it should be returned.
So i'm trying to use .setParameterList, like this:
List<BloqueCruzamiento> bloques = session.createQuery("FROM BloqueCruzamiento AS b WHERE b.anio=:anio AND b.activo=true AND b.grupo=:categoria AND b.pr IN(:pr_set)ORDER BY b.nroParcela, b.cruza, b.pedigree")
.setParameter("anio", grupo.getAnio())
.setParameter("categoria", grupo.getCategoria())
.setParameterList("pr_set", pr_parm)
.list();
the quid is on "pr_set" parameter.
I want to know how to convert a String , "0123", to a Collection of Integers (0,1,2,3).
So I can pass this parameter to setParameterList() method.
Anapproach that I'm right now is to convert the String to a Char Array, then loop, and convert each element into an Integer Array.
Can somebody give anothe solution ?
Regards
you can use code below to get list from String
String s = "0123";
List<Integer> pr_parm = new ArrayList<Integer>();
for(int i=0;i<s.length();i++) {
if (Character.isDigit(s.charAt(i))) {
pr_parm.add(Integer.parseInt(String.valueOf(s.charAt(i))));
}
}
System.out.println(pr_parm);
Then you can use the list in your setParameterList("pr_set", pr_parm)
this was the solution.
String[] sele = grupo.getPr_sel().split(",");
Integer[] pr_parm_int = new Integer[sele.length];
for (int x=0; x<sele.length;x++){
pr_parm_int[x] = Integer.valueOf(sele[x]);
}
the first line is to parse the string and strip comas.
Related
i have a dynamic list.
list=['a','b','c','d' ..... ] so length may change
i want to compare these list values in a query
select * from student where name in(all the list values);
i want to pass list values into this query
how i can do this.. ??? please help
Thank you
In Postgres, you can use arrays. The syntax in the where clause looks like:
where name = any (array[1, 2, 3])
or
where name = any (list_parameter)
You can write a function that gets a list as a parameter and return a string like "'one', 'two','three'".
// need a string like this 'one', 'two'
private String arrayToSqlInChecker(List<String> loc_list) {
StringBuilder value = new StringBuilder("");
for (int i = 0; i < loc_list.size(); i++) {
value.append("'" + loc_list.get(i) + "'");
if (i != loc_list.size() - 1) {
value.append(",");
}
}
return value.toString();
}
And then you have to append this string into you PostgreSQL IN query
"id IN (" + this.arrayToSqlInChecker(loc_list) + ")"
You can also handle null or empty values in the function
I've a query on sqlite that use "between" and I want to use it on standard Query.
my code is here:
String[] columns = new String[]{"_id", "question_group", "question_number", "is_answered"};
String selection = "question_group = ?";
String[] selectionArgs = new String[]{String.valueOf(category)};
String groupBy = null;
String having = null;
String orderBy = null;
String limit = null;
SQLiteDatabase db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READWRITE);
Cursor cursor = db.query(TABLE_QUESTION, columns, selection, selectionArgs, groupBy, having, orderBy, limit);
I want to Add another condition that is :question_number between 1 and 10. I can now write this query in a single statement but I want to use it as above I told.
From the Android documentation describing the selection parameter of the query() method:
A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given table.
If you want the following WHERE clause in your query
WHERE question_group = :category AND question_number BETWEEN 1 AND 10
then you can use the following selection and selectionArgs:
String selection = "question_group = ? AND question_number BETWEEN ? AND ?";
String[] selectionArgs = new String[]{ String.valueOf(category), "1", "10"};
A property from my object (oJobs) is as follows:
Private _brandlist As List(Of DAL.Brand)
Public Property PostBrandList() As List(Of DAL.Brand)
Get
Return _brandlist
End Get
Set(ByVal value As List(Of DAL.Brand))
_brandlist = value
End Set
End Property
In the database, the brand list is stored as a string separated by comma e.g. the column 'brands' can be a string '3,45,2' where each number represents an id of a brand stored in another table.
my select query is as below:
Dim jobposts As List(Of oJobs) = From j In db.JobPostings
Select New oJobs With { 'hiding all others for code brevity
.PostBrandList = 'problem is here'
}
Since j.BrandList will return a string, I will need to split that string and for each number, run another query to finally return and assign a List(Of DAL.Brand) into .PostBrandList
For those who might ask "what have you tried?",
I have run the query, then did a for each to add the list of brands later - succeeded but not optimal
Coded a function that takes the list as a parameter and returns a separate list of objects - very silly.
Also, I am not allowed to normalize the DB :(
Not tested and might need some tweaking but heres one idea. you will also need to change your property to an IEnumerable rather than List. Because the second linq query is embedded within the first, I believe it should execute it all as one query, but you should check it to make sure.
Dim jobposts As List(Of oJobs) = From j In db.JobPostings
Select New oJobs With { 'hiding all others for code brevity
.PostBrandList = From b In db.Brands Where j.Brands = b.ID Or j.Brands.StartsWith(b.ID & ",") Or j.Brands.EndsWith("," & b.ID) Or j.Brands.Contains("," & b.ID & ",") Select b
}
In c# you can use
.Select(x=>new {x.BrandList})
.ToList() //Materialize first before calling function
.Select(x=> new oJobs{
PostBrandList =
db.Brands.Where(z=>
x.BrandList
.Split(',')
.Select(y=>int.Parse(y.Trim()))
.Contains(z.Id))
.ToList()
});
Note that you must materialize entity first before calling String.Split
I don't know how to translate that to VB.NET.
Of course it will cause SELECT n+1 problem because you can't use join.
If you can't normalize table, my other suggestion is to create indexed view (sql server), so you can use join and improve performance.
Indexed view https://msdn.microsoft.com/en-us/library/ms191432.aspx
You could try it with the Let statement:
Dim jobposts As List(Of oJobs) = From j In db.JobPostings
/* li in the LINQ Statement represents one string value from the BrandList list */
Let postBrandElemsList = j.BrandList.Split(',').Select(Function(li) New DAL.Brand With { ... /* Field initializatione of the Class DAL.Brand here */ }
Select New oJobs With
{
.PostBrandList = postBrandElemsList
}
I'm sorry for the probably bad VB.NET syntax, you should check this when implementing it in your code.
Maybe you would just want to use the Split function on the column brands into an array and iterate through the result, using the Find function to retrieve the brand objects?
Somehow i got filename.log which looks like for example (tab separated)
Name:Peter Age:18
Name:Tom Age:25
Name:Jason Age:35
because the value of key column may differ i cannot define schema when i load text like
a = load 'filename.log' as (Name:chararray,Age:int);
Neither do i want to call column by position like
b = foreach a generate $0,$1;
What I want to do is, from only that filename.log, to make it possible to call each value by key, for example
a = load 'filename.log' using PigStorage('\t');
b = group b by Name;
c = foreach b generate group, COUNT(b);
dump c;
for that purpose, i wrote some Java UDF which seperate key:value and get value for every field in tuple as below
public class SPLITALLGETCOL2 extends EvalFunc<Tuple>{
#Override
public Tuple exec(Tuple input){
TupleFactory mTupleFactory = TupleFactory.getInstance();
ArrayList<String> mProtoTuple = new ArrayList<String>();
Tuple output;
String target=input.toString().substring(1, input.toString().length()-1);
String[] tokenized=target.split(",");
try{
for(int i=0;i<tokenized.length;i++){
mProtoTuple.add(tokenized[i].split(":")[1]);
}
output = mTupleFactory.newTupleNoCopy(mProtoTuple);
return output;
}catch(Exception e){
output = mTupleFactory.newTupleNoCopy(mProtoTuple);
return output;
}
}
}
How should I alter this method to get what I want? or How should I write other UDF to get there?
Whatever you do, don't use a tuple to store the output. Tuples are intended to store a fixed number of fields, where you know what every field contains. Since you don't know that the keys will be in Name,Age form (or even exist, or that there won't be more) you should use a bag. Bags are unordered sets of tuples. They can have any number of tuples in them as long as the tuples have the same schema. These are all valid bags for the schema B: {T:(key:chararray, value:chararray)}:
{(Name,Foo),(Age,Bar)}
{(Age,25),(Name,Jim)}
{(Name,Bob)}
{(Age,30),(Name,Roger),(Hair Color,Brown)}
{(Hair Color,),(Name,Victor)} -- Note the Null value for Hair Color
However, it sounds like you really want a map:
myudf.py
#outputSchema('M:map[]')
def mapize(the_input):
out = {}
for kv in the_input.split(' '):
k, v = kv.split(':')
out[k] = v
return out
myscript.pig
register '../myudf.py' using jython as myudf ;
A = LOAD 'filename.log' AS (total:chararray) ;
B = FOREACH A GENERATE myudf.mapize(total) ;
-- Sample usage, grouping by the name key.
C = GROUP B BY M#'Name' ;
Using the # operator you can pull out all values from the map using the key you give. You can read more about maps here.
Supposed that I have two arrays:
Dim RoomName() As String = {(RoomA), (RoomB), (RoomC), (RoomD), (RoomE)}
Dim RoomType() As Integer = {1, 2, 2, 2, 1}
I want to get a value from the "RoomName" array based on a criteria of "RoomType" array. For example, I want to get a "RoomName" with "RoomType = 2", so the algorithm should randomize the index of the array that the "RoomType" is "2", and get a single value range from index "1-3" only.
Is there any possible ways to solve the problem using array, or is there any better ways to do this? Thank you very much for your time :)
Note: Code examples below using C# but hopefully you can read the intent for vb.net
Well, a simpler way would be to have a structure/class that contained both name and type properties e.g.:
public class Room
{
public string Name { get; set; }
public int Type { get; set; }
public Room(string name, int type)
{
Name = name;
Type = type;
}
}
Then given a set of rooms you can find those of a given type using a simple linq expression:
var match = rooms.Where(r => r.Type == 2).Select(r => r.Name).ToList();
Then you can find a random entry from within the set of matching room names (see below)
However assuming you want to stick with the parallel arrays, one way is to find the matching index values from the type array, then find the matching names and then find one of the matching values using a random function.
var matchingTypeIndexes = new List<int>();
int matchingTypeIndex = -1;
do
{
matchingTypeIndex = Array.IndexOf(roomType, 2, matchingTypeIndex + 1);
if (matchingTypeIndex > -1)
{
matchingTypeIndexes.Add(matchingTypeIndex);
}
} while (matchingTypeIndex > -1);
List<string> matchingRoomNames = matchingTypeIndexes.Select(typeIndex => roomName[typeIndex]).ToList();
Then to find a random entry of those that match (from one of the lists generated above):
var posn = new Random().Next(matchingRoomNames.Count);
Console.WriteLine(matchingRoomNames[posn]);