Comparison of multiselect picklist with a field in text format in apex - salesforce

I have an object with number of records in this format with Name in Text format -
Id Name
1 A,B,C
2 A,B
3 A
4 B
5 A,C
6 A,D
I have a multi-select picklist with values as:
A
B
C
D
So if I select B and C in my picklist, then I must have the records from the table in which name consists of B or C or (B and C) i.e. in this case, it should show 4 records:
1 A,B,C
2 A,B
4 B
5 A,C
I am using SQL query with IN and INCLUDES keyword but I am unable to achieve this functionality.

This depends on how many options you have for using soql. One way I can see it is:
Object__c myObject = new Object__c();
object.Name = 'A,B,D';
object.Multi_Select_Name__c = 'A;E';
insert object;
String query = 'select Id from Object__c';
//now we want to do a multi picklist, which is a String separated by ';'
List<String> nameSelections = object.Multi_Select_Name__c.split(';');
if(nameSelections.size() > 0) {
query += ' where ';
for(Integer i = 0; i < nameSelections.size(); i++) {
nameSelections[i] = 'Name like \'%' + nameSelections[i] + '%\'';
}
query += String.join(nameSelections, ' or ');
}
List<Object__c> objects = (List<Object__c)database.query(query);
This will create a query like:
'select Id from Object__c where Name like '%A%' or Name like '%E%'
Selecting all Object__c's where Name contains either A or E, generated from your multiselect.
Syntax errors may apply, I just wrote this real quick :) Ill double check myself.
EDIT:
This code works to build the query
String query = 'select Id from Object__c';
String multiSelect = 'A;E';
List<String> nameSelections = multiSelect.split(';');
if(nameSelections.size() > 0 ){
query += ' where ';
for(Integer i = 0; i < nameSelections.size(); i++) {
nameSelections[i] = 'Name like \'%' + nameSelections[i] + '%\'';
}
query += String.join(nameSelections, ' or ');
}
system.debug(LoggingLevel.INFO, query);

Related

How to Query Data with Specified Multiple Field Values?

I have a table as follows:
Id = stretch(1..100,1000)
area = take(`A`B`C`D`E`F`G`H`I`J,1000)
qyt = rand(100.00,1000)
t = table(Id,area,qyt)
I want to query data with multiple field values.
Query condition:
field value “Id=1“, “area“ = A, F, G;
field value “Id=2“, “area“ = B, C, D;
field value “Id=3“, “area“ = B, C, G;
I tried the following method, querying each record with a where clause.
select * from t where (Id =1 and area = `A) or (Id = 1 and area = `F) or(Id = 1 and area = `G)
The code is simple but long. Is there any easier way to solve this problem?
The query condition involves field “Id“ and “area“. First, you can add a new field “newCol“ that combines these two fields.
temp = select *,string(Id)+area as newCol from t
Then, conduct a query as follows:
aim_row = `1A`1F`1G`2B`2C`2D`3B`3C`3G
result = select Id,area, qyt from temp where newCol in aim_row
Output:
Id area qyt
-- ---- ------------------
1 A 30.710145598277449
1 F 37.276206677779555
1 G 81.456008832901716
2 B 47.396290418691933
2 C 68.868489493615925
2 D 72.536952490918338
3 B 77.235422702506184
3 C 32.31446212157607
3 G 39.283064194023609

Getting System.QueryException: line 1:40 no viable alternative at character '\'

Am using a dynamic query to get data. Below is my code
if(objVal != null){
sObject obj = Schema.getGlobalDescribe().get(objVal).newSObject();
if(ConditionVal== null || ConditionVal=='')
query = 'Select Id From '+objVal+ ' Limit 10000';
else{
ConditionVal= String.escapeSingleQuotes(ConditionVal);
query = 'Select Id From '+selectedObj+' WHERE '+ConditionVal+' LIMIT 10000';
}
List<SObject> objlst = Database.query(query);
Am getting "objVal" , "ConditionVal" value form VF page
Example objVal = 'Account' ConditionVal = 'industry = 'Apparel'
after executing the code am getting the query like this
Select Id From Account WHERE industry = \'Apparel\' LIMIT 10000
update the value of ConditionVal variable as below,
ConditionVal = 'Industry = \'Apparel\'';
the query will work as expected.

Can Any one help me to convert this sql query into linq

I need to convert this SQL Query to Link :
"Select * FROM [Register]
where RegisterId IN (SELECT MyId
FROM Friends
WHERE FriendId='" + Session["CurrentProfileId"] + "'
AND Status=1
UNION
SELECT FriendId
FROM Friends
WHERE MyId='" + Session["CurrentProfileId"] + "'
AND Status=1) ";
It may be look like this??? but this is incorrect and having errors
(from u in db.Register
where RegisterId).Contains
(from f in db.Freinds
where f.MyId == Id && m.Status == 1
select new { m.MyId })
.Union(from m in db.Freinds
where f.FreindId == Id && m.Status == 1
select new { m.CreateDate } ));
You have a few problems with the linq above and here are a few:
In the query in the Union you select the CreateDate whereas in the top on you select the MyId. I assume you meant to select FreindId.
In these 2 queries you create an anonymous class instance with the field but then compare it to the RegisterId which is probably a guid/string/int - but for sure not of the type you just created.
You are using the Contains method wrong. Linq syntax can be similar to sql but it is not the same. Check here for Contains
The correct Linq way of doing it is:
var idsCollection = ((from f in db.Freinds
where f.StatusId == 1 && f.MyId == Id
select f.MyId)
.Union(from m in db.Friends
where m.StatusId == 1 && f.FreindId == Id
select m.FriendId)).ToList();
var result = (from u in db.Register
where idsCollection.Contains(u.RegisterId)
select u).ToList();
Notice that the .ToList() is not a must and is here just to ease in debugging. For more information about this .ToList() and Linq in general check MSDN

Linq query count

select count(tblVV.VNme) as total,
tblvV.VNme
from tblVV
inner join tblRV
on tblVV.MID=tblRV.ID
inner join tblRe
on tblRV.RID=tblRe.RID
where tblRe.StartDate>= '2016-07-01 00:00:00' and
tblRe.EndDate<= '2016-07-31 23:59:59' and
tblRe.Reg= 'uk' and
tblRV.RegNo='BR72' and
tblVV.VNme <>''
group by tblVV.VNme
For the above query I get:
total Vame
1 DDSB
11 MV
The above SQL query shows me correct data so now i try to convert above query to linq query
[WebMethod]
public static string GetVo(string RegNo)
{
string data = "[";
try
{
Ts1 DB = new Ts1();
var re = (from vehvoila in DB.tblVV
join regveh in DB.tblRV on vehvoila.MID equals regveh.ID
join reg in DB.tblReg on regveh.RID equals reg.RID
where regveh.RegNo == RegNo &&
vehvoila.Vame != ""
group vehvoila by vehvoila.Vame into g
select new
{
VNme = g.Key,
cnt = g.Select(t => t.Vame).Count()
}).ToList();
if (re.Any())
{
data += re.ToList().Select(x => "['" + x.Vame + "'," + x.cnt + "]")
.Aggregate((a, b) => a + "," + b);
}
data += "]";
}
linq query show me return data like this
[['DDSB',1],['DPSB',1],['DSB',109],['MV',39],['PSB',1]]
Whereas I want data this
[['DDSB',1],['MV',11]]
Now the data which return SQL query is correct so how I correct linq query
Note: forget fromdate,todate,region parameter in SQL query . because I have page in which I put dropdown and fromdate and todate picker and there is button so when I select values i.e. UK, and dates then data is display in table then when I click on any row in table then I want to get this data in data +=”]”;
actually above linq query work behind clicking on row
total Vame
1 DDSB
11 MV
You can write it all like this:
Ts1 db = new Ts1();
var result = (from vehvoila in db.tblVV
join regveh in db.tblRV on vehvoila.MID equals regveh.ID
join reg in db.tblReg on regveh.RID equals reg.RID
where reg.StartDate >= new DateTime(2016, 7, 1) &&
reg.EndDate < new DateTime(2016, 8, 1) &&
reg.Reg == "uk" &&
regveh == "BR72" &&
vehvoila != ""
group vehvoila by vehvoila.Vame into g
select $"[{g.Key},{g.Count()}]");
var data = $"[{string.Join(",", result)}]";
Because you only use the result for the creation of the string in the select I just return the string formatted for a single item and then later used string.Join instead of using the .Aggregate - I think a bit cleaner
The $"{}" syntax is the C# 6.0 string interpolation
In the condition of the EndDate I decided to use < instead of the <= with the change of the date - At least in oracle when you partition the table by date it is better for performance - maybe also in sql server
Without string interpolation:
Ts1 db = new Ts1();
var result = (from vehvoila in db.tblVV
join regveh in db.tblRV on vehvoila.MID equals regveh.ID
join reg in db.tblReg on regveh.RID equals reg.RID
where reg.StartDate >= new DateTime(2016, 7, 1) &&
reg.EndDate < new DateTime(2016, 8, 1) &&
reg.Reg == "uk" &&
regveh == "BR72" &&
vehvoila != ""
group vehvoila by vehvoila.Vame into g
select new { Key = g.Key, Count = g.Count()})
.AsEnumerable()
.Select(g => string.Format("[{0},{1}]",g.Key, g.Count));
var data = string.Format("[{0}]",string.Join(",", result));

slow SQLite read speed (100 records a second)

I have a large SQLite database (~134 GB) that has multiple tables each with 14 columns, about 330 million records, and 4 indexes. The only operation used on the database is "Select *" as I need all the columns(No inserts or updates). When I query the database, the response time is slow when the result set is big (takes 160 seconds for getting ~18,000 records).
I have improved the use of indexes multiple times and this is the fastest response time I got.
I am running the database as a back-end database for a web application on a server with 32 GB of RAM.
is there a way to use RAM (or anything else) to speed up the query process?
Here is the code that performs the query.
async.each(proteins,function(item, callback) {
`PI[item] = []; // Stores interaction proteins for all query proteins
PS[item] = []; // Stores scores for all interaction proteins
PIS[item] = []; // Stores interaction sites for all interaction proteins
var sites = {}; // a temporarily holder for interaction sites
var query_string = 'SELECT * FROM ' + organism + PIPE_output_table +
' WHERE ' + score_type + ' > ' + cutoff['range'] + ' AND (protein_A = "' + item + '" OR protein_B = "' + item '") ORDER BY PIPE_score DESC';
db.each(query_string, function (err, row) {
if (row.protein_A == item) {
PI[item].push(row.protein_B);
// add 1 to interaction sites to represent sites starting from 1 not from 0
sites['S1AS'] = row.site1_A_start + 1;
sites['S1AE'] = row.site1_A_end + 1;
sites['S1BS'] = row.site1_B_start + 1;
sites['S1BE'] = row.site1_B_end + 1;
sites['S2AS'] = row.site2_A_start + 1;
sites['S2AE'] = row.site2_A_end + 1;
sites['S2BS'] = row.site2_B_start + 1;
sites['S2BE'] = row.site2_B_end + 1;
sites['S3AS'] = row.site3_A_start + 1;
sites['S3AE'] = row.site3_A_end + 1;
sites['S3BS'] = row.site3_B_start + 1;
sites['S3BE'] = row.site3_B_end + 1;
PIS[item].push(sites);
sites = {};
}
}
The query you posted uses no variables.
It will always return the same thing: all the rows with a null score whose protein column is equal to its protein_a or protein_b column. You're then having to filter all those extra rows in Javascript, fetching a lot more rows than you need to.
Here's why...
If I'm understanding this query correctly, you have WHERE Score > [Score]. I've never encountered this syntax before, so I looked it up.
[keyword] A keyword enclosed in square brackets is an identifier. This is not standard SQL. This quoting mechanism is used by MS Access and SQL Server and is included in SQLite for compatibility.
An identifier is something like a column or table name, not a variable.
This means that this...
SELECT * FROM [TABLE]
WHERE Score > [Score] AND
(protein_A = [Protein] OR protein_B = [Protein])
ORDER BY [Score] DESC;
Is the same as this...
SELECT * FROM `TABLE`
WHERE Score > Score AND
(protein_A = Protein OR protein_B = Protein)
ORDER BY Score DESC;
You never pass any variables to the query. It will always return the same thing.
This can be seen here when you run it.
db.each(query_string, function (err, row) {
Since you're checking that each protein is equal to itself (or something very like itself), you're likely fetching every row. And it's why you have to filter all the rows again. And that is one of the reasons why your query is so slow.
if (row.protein_A == item) {
BUT! WHERE Score > [Score] will never be true, a thing cannot be greater than itself except for null! Trinary logic is weird. So only if Score is null can that be true.
So you're returning all the rows whose score is null and the protein column is equal to protein_a or protein_b. This is a lot more rows than you need, I guess you have a lot of rows with null scores.
Your query should incorporate variables (I'm assuming you're using node-sqlite3) and pass in their values when you execute the query.
var query = " \
SELECT * FROM `TABLE` \
WHERE Score > $score AND \
(protein_A = $protein OR protein_B = $protein) \
ORDER BY Score DESC; \
";
var stmt = db.prepare(query);
stmt.each({$score: score, $protein: protein}, function (err, row) {
PI[item].push(row.protein_B);
...
});

Resources