SQLite Query issue - objective-c

I have a DB having 3 tables like
Name(PK_NameId, FK_ContactId, FK_FavId, length)
Contact(PK_ContactId)
Favourites(PK_FavId)
In my iPhone app, there are various options(criterias) to search the name as user can select multiple names, user can select multiple contacts, user can select multiple favourites & also user can select length like 0-10, 10-20 etc. Also user can click search button without any criteria to get all the names.
I am new in SQLite & wants to create a query for searching the name by considering above all cases without the if-else condition through coding which takes less amount of time for query execution.
I know one option to check which criteria user is selected & apply if-else condition but it is not too good so I want to handle it through query.
If anyone knows it then please help me.

I got the solution using the following way -
NSString *strQuery;
strQuery = [NSString stringWithFormat:#"SELECT N.PK_NameId FROM Name N inner join Contact C on C.PK_ContactId = N.FK_ContactId inner join Favourites F on F.PK_FavId = N.FK_FavId where ((1)"];
after this, I checked the null value of each selection type(name, contact, list) & append the query to the original query. Finally complete the query using the closing brace which was I opened after where clause in main query.
strQuery = [NSString stringWithFormat:#"%#)", strQuery];

Related

How to process a table serially for count

I need to process through a list of technical skills one by one and get a count of the number of developers we have in 3 locations who have that skill. For example, car type = "Java". How many persons have this skill listed in their resume.
I have 2 tables:
Skills: contains a single column listing skills - "Java" for example
Resources: contains 4 columns, Resource-ID, Name, Location, and a long text field called "Resume" containing text of their resume.
If this were a single skill I would process the SQL something like below (SQL syntax not exact)
SELECT count FROM [Resources] WHERE ([Resources].[Resume] Like "SKILL-ID*");
I want to process the Skills table serially printing the "Skill" and the count in each location.
Help appreciated
I've only used Access as a DB for single record retrieval, never using table values as input to loop through a process. I suspect that this is a simple execution in MS Access.
Ok, so we have to process that table.
I would simple "send out" a row with Location and skill for each match. We could write some "messy" code to then group by, but that is what SQL is for!!!
We could quite easy keep/have/use/enjoy the results in code, but its better to send the results out to a working table. Then we can use what sql does best - group and count that data.
So, then, the code could be this:
Sub CountSkills()
' empty out our working report table
CurrentDb.Execute "DELETE * FROM ReportResult"
Dim rstSkills As DAO.Recordset
Dim rstResources As DAO.Recordset
Dim rstReportResult As DAO.Recordset
Dim strSQL As String
Set rstSkills = CurrentDb.OpenRecordset("Skills")
strSQL = "SELECT Location, Resume FROM Resources " & _
"ORDER BY Location"
Set rstResources = CurrentDb.OpenRecordset(strSQL)
Set rstReportResult = CurrentDb.OpenRecordset("ReportResult")
Do While rstResources.EOF = False
' now for each resource row, process skill set
rstSkills.MoveFirst
Do While rstSkills.EOF = False
If InStr(rstResources!Resume, rstSkills!Skill) > 0 Then
rstReportResult.AddNew
rstReportResult!Location = rstResources!Location
rstReportResult!Skill = rstSkills!Skill
rstReportResult.Update
End If
rstSkills.MoveNext
Loop
rstResources.MoveNext
Loop
End Sub
Now, the above will wind up with a table looking like this:
So, now we can query (and count) against above data.
So, this query would do the trick:
SELECT Location, Skill, Count(1) AS SkillCount
FROM ReportResult
GROUP BY Location, Skill
And now we get this:
And you can flip the above query to group by skil, then location if you wish.
so, at the most simple level?
We write out ONE row + location for every match, and then use SQL on that to group by and count.
We COULD write code to actually count up by location, but that VBA code would as noted be a bit messy, and just spitting out rows of location and skill means we can then group by skill count, skill location count, or location, skill counts just by using "simple" sql against that list of location and skill record list.
So, now use the report wizard on that query above, and we get something like this:
Of course it is simple to change around the above report, but you get the idea for such a simple task as you noted.
Summarizing count of developers by skill and location can be accomplished with SQL. It requires a dataset of all possible skill/location pairs. Consider this simple example:
Resources
ID
Name
Location
Resume
1
a
x
Java,Excel
2
b
x
Excel
3
c
y
Excel
4
d
z
VBA,Java
SELECT Skills.SkillName, Resources.Location,
Sum(Abs([Resume] Like '*' & [SkillName] & "*")) AS DevCt
FROM Skills, Resources
GROUP BY Skills.SkillName, Resources.Location;
SkillName
Location
DevCt
Excel
x
2
Excel
y
1
Excel
z
0
Java
x
1
Java
y
0
Java
z
1
VBA
x
0
VBA
y
0
VBA
z
1
This approach utilizes a Cartesian product of Skills and Resources tables to generate the data pairs. This type of query can perform slowly with large dataset. If it is too slow, saving the pairs to a table could improve performance. Otherwise, a VBA solution will be only recourse and would likely involve looping recordset object.
Regardless of approach, be aware results will be skewed if Resume has content like "excellence". Bad data output is pitfall of poor database design.
Solution:
Resource and Skill table were added into MS_Access
Step 1: Create a query that executes the below SQL to get a counts (here named "Step1Query"):
SELECT Skills.SkillName, Resources.Location,
Sum(Abs([Resume] Like '*' & [SkillName] & "*")) AS DevCt
FROM Skills, Resources
GROUP BY Skills.SkillName, Resources.Location;
Step 2: Create a second query that uses the Step 1 query as input. (you can do this via the wizard):
TRANSFORM Sum(Step1Query.DevCt) AS SumOfDevCt
SELECT Skills.SkillName, Resources.Location,
Sum(Abs([Resume] Like '*' & [SkillName] & "*")) AS DevCt
FROM Skills, Resources
GROUP BY Skills.SkillName, Resources.Location
PIVOT Step1Query_qry.[Location];
Result lists out a matrix form. Thanks all for your help.

How to run a sql query multiple times and combine the results into single output?

I have a list of 2500 obj numbers stored in Excel for which I need to run the below SQL:
SELECT
a.objno,
a.table_comment,
b.queue_comment
FROM
aq$_queue_tables a
JOIN
AQ$_QUEUES b ON a.objno = b.table_objno
WHERE
a.objno = 19551;
Is there any way I can write a loop on above SQL with objno feeding from a list or from a different table? I also want to store/produce all the results from each loop run as a single output.
I considered the option to upload the numbers into a new table and add a where condition:
a.objno=(SELECT newtab.objectno FROM newtab);
However, the logic I'll be writing in the query would exclude certain objectno results. Let's say that the associated objectno has certain queue_comment as of certain date associated with that objectno. I do not want to pull that record. This condition would match with some objectno and wouldn't match with others. Having that condition and running the query against all the objectno is returning 0 results. I couldn't share the original logic as it would reveal certain business rules and it'll be a violation of some policy.
So, I need to run the query on each objectno separately and combine the results.
I'm totally new to SQL and got this task assigned. I'm aware of the regular loop, for in SQL, but I don't think I can apply them in this situation.
Any guidance or reference links to helpful topics is much appreciated as well.
Thanks in advance for the help.
One option is to upload the object numbers from Excel sheet to a table in the database and run the query as following. Assuming newtab is the table where the objectno are uploaded.
SELECT
a.objno,
a.table_comment,
b.queue_comment
FROM
aq$_queue_tables a JOIN AQ$_QUEUES b on a.objno = b.table_objno
WHERE
a.objno IN (SELECT newtab.objectno FROM newtab);
I have used a subquery here, join to the aq$ can work as well.
Reading the comments and all I think you need to enhance your Excel with 2 additional columns and load to a new table.
IN can be used in the following way too:
SELECT
a.objno,
a.table_comment,
b.queue_comment
FROM
aq$_queue_tables a
JOIN
AQ$_QUEUES b ON a.objno = b.table_objno
WHERE
(a.objno,a.table_comment,b.queue_comment) IN (19551,'something','something');
so with the new table will be:
WHERE
(a.objno,a.table_comment,b.queue_comment) IN
(select n.objno, n.table_comment, n.queue_comment from new_table n)

How to select data with a complex condition?

Using Microsoft Access, I normally use condition (mostly where) to obtain the data I want to display.
So far, it went well. However now I have a complex filtering and I'm not sure of the best way to do it. I will explain how I do it with many queries, and I'd like to know if there is something simpler, since I feel like it's doing too much for what I accomplish.
I have Building and Energy tables. Between them, I have a link table since a Building has a list of possible energies.
My goal is to display ALL energy not already associated with the building.
I first have a simple query to display all the IDs of energy that are in the link table where building is the one of interest.
Once I do that, I have another query using this one, which display an energy if it is an energy absent from previous list.
This takes 2 queries and I feel like I could have a better way to do this. I'm fairly new to MS Access, so any suggestion is welcome.
Here is the first request to obtain the list of energies:
SELECT
Batiments.ID, Energies.ID, Energies.Type
FROM
Energies
INNER JOIN
(Batiments
INNER JOIN
Batiment_Energie ON Batiments.ID = Batiment_Energie.Batiment_ID) ON Energies.ID = Batiment_Energie.Energie_ID
WHERE
(((Batiments.ID) = " & cbxBatiments.Column(0) & "));"
You can query the non-associated energy types with
SELECT
ID, Type
FROM
Energies
WHERE
ID NOT IN (SELECT Energie_ID
FROM Batiment_Energie
WHERE Batiment_ID = 123)
where 123 is to be replaced by the Id comming from cbxBatiments.Column(0).
You can use not exists:
select e.*
from energie as e
where not exists (select 1
from Batiment_Energie as be
where be.energie_id = e.id and be.batiment_id = <your id>
);

Insert textbox value into Access SQL query

Being an amateur in Access and VBA, I've hit a wall with the following...
In MS Access 2007, I have the following query:
SELECT .... WHERE format(NZ(l_f_date),'yyyy-mm-dd')<=**'2012-04-03'**);
I have shortened it a bit of course.
The database has approx 20 queries that need to be run on a daily basis. I have created 4 macros to run groups of queries in the manner that I need them to be run. The problem is that in every one of those queries I first have to change the date (like in the upper query). I am looking for the way to automate it a bit more.
I have an idea to create a Form, place a button for every macro on it and 2 textbox-es to enter the 2 dates I need. Now, I need those dates to appear in the bolded part. As I think about it, I have 2 options:
Create a temporary table in the database to store those two dates and pull those 2 fields in my queries.
Insert the value of the textbox somehow directly into the bolded part of the query.
I think I can manage the first solution, but the second one is making my head hurt.
Can you help?
SQL from comment
select proc_desc,count(s) as broj
into upit3
from ( select distinct a.case_id as s,
a.org_case_id,a.act_date as day,d.prod_id,d.prod_desc,
c.fname,c.dpd,c.due_amount,proc_id,proc_desc
from actions_b as a, cases_old_b as c,processes_b as p,
product_dict_b as d
where a.org_case_id=c.[org_ case_id]
and a.act_date=Forms!Form!Text10 and d.prod_id=c.product
and p.proc_id=c.process and not_lead=1 )
group by proc_desc order by proc_desc;
OK, sample data....
In x.dates, value is exactly like this: 03.04.2012
In a.act_date value is like this: 01.07.2011 13:53:56
so if its not possible with this values as they are, is it possible to use a LIKE statement in the query? Pseudo: WHERE a.act_date LIKE x.date%
If its possible, how to use it? i am a novice in sql and access queries... I google but sometimes, like this time, i get stuck.
Thanks
This structure:
SELECT .... WHERE format(NZ(l_f_date),'yyyy-mm-dd')<='2012-04-03');
Is not a good idea. The general rule is to try and stick to field (column) names on the left side of the equals. So
SELECT .... WHERE l_f_date <=#2012-04-03#
Nulls will not be included and I hope your dates are dates and not strings.
Next add the form:
SELECT .... WHERE l_f_date <= Forms!TheNameOfTheForm!TheNameOfTheTextbox
EDIT re comments
You are using the query design window, yes? Please try this test query:
SELECT a.case_id, a.act_date
FROM actions_b AS a
WHERE a.act_date=Forms!Form!Text10
OK, so i decided to create a simple 2-column table in my database that will be used just for storing yesterdays and todays date... i added 2 text-boxes to a form, 1 button and added the next procedure to the button:
Private Sub Command25_Click()
CurrentDb.Execute "DELETE * FROM Datumi"
Dim tbl As Recordset
Set tbl = CurrentDb.OpenRecordset("Datumi")
tbl.AddNew
tbl!brojka = "1"
tbl!datum = Text8.Value
tbl.Update
tbl.AddNew
tbl!brojka = "2"
tbl!datum = Text10.Value
tbl.Update
End Sub
As you can see, the click on the button will clear the table and store new values into 2 rows... row 1 is yesterday, row 2 is today...
And after that im pulling the values from that table like this:
... where x.brojka=1 and format(a.act_date,'yyyy-mm-dd')=format(x.datum,'yyyy-mm-dd') ...
I'm sure it can be done better but this one works for me...
I Solved this problem with :
[Software: MS Access 2013]
CurrentDb.Execute "INSERT INTO [Inventory Transactions] ([Product ID], [Order ID])" _
& "VALUES ( " & Me.Product_ID & ", " & Me.Order_ID & ")"

SQL - multiple conditions in DCount() function

I am using MS Access 2007.
A: DCount("[Name]","[Main]","[Name] = 'Mark'")/
DCount("[Entry]","[Main]","[Entry] = 1")
Okay, so I am basically counting the number of people with the name Mark and I am dividing it by the number of Entry's that = 1 in my database. That's easy enough, but I am trying to apply a third condition, where
[Location]![City] = 'Chicago'
, but Access isn't letting me do this (It can't find the table, even though it's in the table I specified above.
DCount("[Name]","[Main]","[Name] = 'Mark' AND [Location]![City] = 'Chicago'")/
DCount("[Entry]","[Main]","[Entry] = 1")
I have also tried filtering the city with a Where clause in the Design view, but the condition is being applied after the calculation above, so the calculation is the same regardless of the city. I just need it to perform the above calculation for the city of Chicago.
Is something like this possible with DCount?
Also, I would die a happy man if you could tell me how to Group By the city While performing the calculations for each one separately, but I would also be very thankful if someone could just show me how to do it the first way too.
Thanks
What is [Location]![City]? My answer is based on the presumption it refers to a field named City in a table named Location.
If that is correct, I think your problem is because you're attempting to specify a condition based on a field which is not part of the domain ([Main]) you told DCount to use.
From Microsoft's Documentation, the domain is "A string expression identifying the set of records that constitutes the domain. It can be a table name or a query name for a query that does not require a parameter."
So if you want your DCount criteria to refer to fields in two tables, consolidate the tables in the form of a query into a single "domain". Maybe your query could be something like this, "qryMainWithCity":
SELECT m.[Name], m.Entry, m.City_ID, l.City
FROM
Main AS m
INNER JOIN Location AS l
ON m.City_ID = l.City_ID;
If that query works for your situation, you should be able to get what you want with a DCount expression like this:
DCount("*","qryMainWithCity","[Name] = 'Mark' AND City = 'Chicago'")
I was just posting the same answer as #HansUp's came up. I have an alternative way to do it, and that's to use an instant recordset lookup:
Dim varReturnValue as Variant
varReturnValue = CurrentDB.OpenRecordset("SELECT Main.[Name] FROM Main INNER JOIN Location ON Main.City_ID = Location.City_ID WHERE Main.[Name] = 'Mark' AND Location.City = 'Chicago';")(0)
That returns the first field in the recordset returned (the index is zero-based). That way you don't have to save a query.