SOQL, Salesforce - Join Two objects with two where clauses - sql

I have two objects named as 'Opportunity' and 'Account.
I need to select ID, OpportunityName,CreatedDate from Opportunity table and AccountName, AccountCat from Account table where Account.OpportunityID = Opportunity.ID and AccountCat = 'DC'.
I refer this tutorial and executed in workbench, but didn't work.
Following is the query I used.
SELECT AccountName, AccountCat (SELECT Id, OpportunityName,CreatedDate FROM Opportunity) FROM Account WHERE OpportunityID
IN (SELECT Id FROM Opportunity) AND AccountCat = 'DC'

Run your query on the Opportunity object and then use reference fields to select fields from the parent object.
SELECT Id
, Name
, CreatedDate
, Account.Name
FROM Opportunity
WHERE Account.Name = 'GenePoint'
AccountCat is not a standard field, so I assume it's a custom field, in which case you need to use the developer name, probably something like Account.Cat__c or Account.Category__c or something like that.
SOQL is superficially similar to SQL, but there are significant differences, one of them being how records are joined.

Related

PostgreSQL - Best approach for summarize data

We have data as follows in system
User data
Experience
Education
Job Application
This data will be used across application and there are few logic also attached to these data.
Just to make sure that this data are consistent across application, i thought to create View for the same and get count of these data then use this view at different places.
Now question is, as detail tables does not have relation with each other, how should i create view
Create different view for each table and then use group by
Create one view and write sub query to get these data
From performance perspective, which one is the best approach?
For e.g.
SELECT
UserId,
COUNT(*) AS ExperienceCount,
0 AS EducationCount
FROM User
INNER JOIN Experience ON user_id = User_Id
GROUP BY
UserId
UNION ALL
SELECT
UserId,
0,
COUNT(*)
FROM User
INNER JOIN Education ON user_id = user_id
GROUP BY
UserId
And then group by this to get summary of all these data in one row per user.
One way to write the query that you have specified would probably be:
SELECT UserId, SUM(ExperienceCount), SUM(EducationCount
FROM ((SELECT UserId, COUNT(*) as ExperienceCount, 0 AS EducationCount
FROM Experience
GROUP BY UserId
) UNION ALL
(SELECT UserId, 0, COUNT(*)
GROUP BY UserId
)
) u
GROUP BY UserId;
This can also be written as a FULL JOIN, LEFT JOIN, and using correlated subqueries. Each of these can be appropriate in different circumstances, depending on your data.

Showing results from multiple tables

I'm working on a legacy Access CRM, for which I have been tasked to add some extra functionality to last us until we can switch to a proper solution.
I have a series of tables representing a one-to-many connection between a Case and various types of Case Notes. These case notes all represent various types of infomation specific to a given workflow (ie an email going into our database needs to have specific fields, which are different than a call), and therefore each different kind of Case Note is represented by a different table. So my table looks something like
Cases
ID
Title
etc...
Case_Emails
ID
Case ID
To Email
From Email
etc...
Case_Calls
ID
Case ID
Caller Email
etc...
Where there are some shared fields between Case Notes, such as Email. One desired feature is to filter a list of email addresses into a ComboBox, based on previous notes tied to a case along with defaults (email addresses used commonly within our day-to-day operations).
Currently, I am using VBA to open a query over each table, then I iterate over the RecordSet capturing unique values. However I would like to pull these from the same query, if possible.
I have been reading on the various type of JOINs, and I do not believe they do what I need.
Can I combine certain fields from different tables to create a list of unique values?
If you're just after a list of emails that occur at least once in at least one of the tables, then this should do the trick.
SELECT t1.emailAdd from
(
select emailField as emailAdd from Case_Emails
union
select emailField as emailAdd from Case_Calls
) t1
group by t1.emailAdd
order by t1.emailAdd
If it must only be emails that occur at least once in at least one of the tables and must be linked to a specific case (for example 12345), then this should do that:
SELECT t1.emailAdd from
(
select emailField as emailAdd from Case_Emails where CaseID=12345
union
select emailField as emailAdd from Case_Calls where CaseID=12345
) t1
group by t1.emailAdd
order by t1.emailAdd
I would like to pull these from the same query, if possible.
Using SQL DLL while in ANSI-92 Query Mode (or do the same manually using the Access GUI tools):
CREATE VIEW CaseEmailAddresses ( case_id, email_address )
AS
SELECT [Case ID], [To Email] FROM Case_Emails
UNION
SELECT [Case ID], [Caller Email] FROM Case_Calls;
Then in SQL DML (queries):
SELECT email_address
FROM CaseEmailAddresses
WHERE case_id = <inject id here>;
Or while you're in ANSI-92 Query Mode, you can create a stored procedure e.g. assuming case_id is type integer:
CREATE PROCEDURE GetEmailAddresses ( :case_id INT )
AS
SELECT case_id, email_address
FROM CaseEmailAddresses
WHERE case_id = :case_id;
Then you can use the technology of your choice to execute this proc while passing the parameter value.

Using multiple columns with counts in access database designer

I am trying to display several columns with different counts in a microsoft access query. It doesn't let me do certain things a normal query can b/c it has the sql design view.
I'd like to display
multiple single etc columns with their counts.
Note: the table names and attributes have been changed.
select (select count(*)as multiple from (select userId from dbo.Purchases
where userId is not null GRoup by userId having count(*)>1) x), (
select count(*)as single from (select userId from dbo.Purchases where
userId is not null GRoup by userId having count(*)=1) x );
if I do these separately I can display it, but I'd like to combine them into one query and one row. Is this possible?
select count(*)as multiple from (select userId from dbo.Purchases
where userId is not null GRoup by userId having count(*)>1) x)
It's very easy with 2 queries:
First one, saved as "Purchases Summary"
Select UserID, count(UserID) as Count from Purchases Group By UserID
With a 2nd built on it:
SELECT Sum(IIf([count]=1,1)) AS [Single], Sum(IIf([count]>1,1)) AS Multiple FROM [Purchases Summary]
I cannot find a clever way to combine this into a single query.
I don't know what my problem last night was, but the single query is
SELECT Sum(IIf([count]=1,1)) AS [Single], Sum(IIf([count]>1,1)) AS Multiple
FROM (Select UserID, count(UserID) as Count from Purchases Group By UserID)
Don George solution also would work.
I ended up using a form and VBA for each column. An issue I had was that I needed to use a distinct call for unique IDs and when there is a sql design view that's not really supported. distinctrow is supported, but it would not work for my query. I ended up writing it as before so that it did not need distinct.
This is the VBA I used to override each input inside of an access form. The currentDb needs to be connected to the database properly before it will also work.
selectStatement = "SELECT Count(* ) FROM (SELECT userID FROM dbo_Purchases WHERE userID is not null GROUP BY userID HAVING count(*)>1) AS x;"
rs = CurrentDb.OpenRecordset(selectStatement).Fields(0).Value
[Text30].Value = rs

how to use distinct in ms access

I have two tables. Task and Categories.
TaskID is not a primary key as there are duplicate values.When there are multiple contacts are selected for a specific task,taskid and other details will be duplicated.I wrote the query:
SELECT Priority, Subject, Status, DueDate, Completed, Category
FROM Task, Categories
WHERE Categories.CategoryID=Task.CategoryID;
Now as multiple contacts are selected for that task,for the taskid=T4, there are two records(highlighted with gray). I have tried using distinct in ms access 2003 but its not working. I want to display distinct records. (Here there's no requirement to show taskid) If I write :
select priority, distinct(subject), .......
and remaining same as mentioned in above query then its giving me an error. I have tried distinctrow also.But didnt get success. How to get distinct values in ms access?
Okay.Its working this way.
SELECT DISTINCT Task.Priority, Task.Subject, Task.Status, Task.DueDate,
Task.Completed, Categories.Category
FROM Task, Categories
WHERE (((Categories.CategoryID)=[Task].[CategoryID]));
I don't like using SELECT DISTINCT, I have found that it makes my code take longer to compile. The other way I do it is by using GROUP BY.
SELECT Priority, Subject, Status, DueDate, Completed, Category
FROM Task, Categories
WHERE Categories.CategoryID=Task.CategoryID
GROUP BY Subject;
I do not have VBA up at the moment but this should work as well.
Using SELECT DISTINCT will work for you, but a better solution here would be to change your database design.
Duplicate records may lead to inconsistent data. For example, imagine having two different status in different records with the same TaskID. Which one would be right?
A better design would include something like a Task table, a Contact table and an Assignment table, as follows (the fields in brackets are the PK):
Tasks: [TaskID], TaskPriority, Subject, Status, DueDate, Completed, StartDate, Owner, CategoryID, ContactID, ...
Contact: [ID], Name, Surname, Address, PhoneNumber, ...
Assignment: [TaskID, ContactID]
Then, you can retrieve the Tasks with a simple SELECT from the Tasks tables.
And whenever you need to know the contacts assigned to a Tasks, you would do so using the JOIN clause, like this
SELECT T.*, C.*
FROM TaskID as T
INNER JOIN Assignment as A
ON T.TaskID = A.TaskID
INNER JOIN Contac as C
ON A.ContactID = C.ID
Or similar. You can filter, sort or group the results using all of SQL's query power.

Distinct Values in SQL Query - Advanced

I have searched high and low and have tried for hours to manipulate the various other queries that seemed to fit but I've had no joy.
I have several Tables in Microsoft SQL Server 2005 that I'm trying to join, an example of which is:
Company Table (Comp_CompanyId, Comp_Name)
GroupCode_Link Table (gcl_c_groupcodelinkid, gcl_c_groupcodeid, gcl_c_companyid)
GroupCode Table (grp_c_groupcodeid, grp_c_groupcode, grp_c_name)
ItemCode Table (itm_c_itemcodeid, itm_c_name, itm_c_itemcode, itm_c_group)
ItemCode_Link Table (icl_c_itemcodelinkid, icl_c_companyid, icl_c_groupcodeid, icl_c_itemcodeid)
I'm using Link Tables to associate a Group to a Company, and an Item to a Group, so a Company could have multiple groups, with multiple items in each group.
Now, I'm trying to create an Advanced Find Function that will allow a user to enter, for example, an Item Code and the result should display those companies that have that item, sounds nice and simple!
However, I haven't done something right, if I use the following query ' if the company has this item OR this item, display it's name', I get the company appearing twice in the result set, once for each item.
What I need is to be able to say is:
"Show me a list of companies that have these items (displaying each company only once!)"
I've had a go at using COUNT, DISTINCT and HAVING but have failed on each as my query knowledge isn't up to it!
First, from your description it sounds like you might have a problem with your E-R (entity-relationship) model. Your description tells me that your E-R model looks something like this:
Associative entities (CompanyGroup, GroupItem) exist to implement many-to-many relationships (since many-to-many isn't supported directly by relational databases).
Nothing wrong with that if a group can exist within multiple companies or an item across multiple groups. It would seem more likely that, at least, each group is specific to a company (I can see items existing across multiple companies and/or groups: more than one company retails, for instance, Cuisinart food processors). If that is the case, a better E-R model would be to make each group a dependent entity with a CompanyID that is a component of its primary key. It's a dependent entity because the group doesn't have an independent existence: it's created by/on behalf of and exists for its parent company. If the company goes away, the group(s) tied to it go away. No your E-R model looks like this:
From that, we can write the query you need:
select *
from Company c
where exists ( select *
from GroupItem gi
where gi.ItemID in ( desired-itemid-1 , ... , desired-itemid-n )
and gi.CompanyID = c.CompanyID
)
As you can see, dependent entities are a powerful thing. Because of the key propagation, queries tend to get simpler. With the original data model, the query would be somewhat more complex:
select *
from Company c
where exists ( select *
from CompanyGroup cg
join GroupItem gi on gi.GroupId = cg.GroupID
where gi.ItemID in ( desired-itemid-1 , ... , desired-itemid-n )
and cg.CompanyID = c.CompanyID
)
Cheers!
SELECT *
FROM company c
WHERE (
SELECT COUNT(DISTINCT icl_c_itemcodeid)
FROM GroupCode_Link gl
JOIN ItemCode_Link il
ON il.icl_c_groupcodeid = gcl_c_groupcodeid
WHERE gl.gcl_c_companyid = c.Comp_CompanyId
AND icl_c_companyid = c.Comp_CompanyId
AND icl_c_itemcodeid IN (#Item1, #Item2)
) >= 2
Replace >= 2 with >= 1 if you want "any item" instead of "all items".
If you need to show companies that have item1 AND item2, you can use Quassnoi's answer.
If you need to show companies that have item1 OR item2, then you can use this:
SELECT
*
FROM
company
WHERE EXISTS
(
SELECT
icl_c_itemcodeid
FROM
GroupCode_Link
INNER JOIN
ItemCode_Link
ON icl_c_groupcodeid = gcl_c_groupcodeid
AND icl_c_itemcodeid IN (#item1, #item2)
WHERE
gcl_c_companyid = company.Comp_CompanyId
AND
icl_c_companyid = company.Comp_CompanyId
)
I would write something like the code below:
SELECT
c.Comp_Name
FROM
Company AS c
WHERE
EXISTS (
SELECT
1
FROM
GroupCode_Link AS gcl
JOIN
ItemCode_Link AS icl
ON
gcl.gcl_c_groupcodeid = icl.icl_c_groupcodeid
JOIN
ItemCode AS itm
ON
icl.icl_c_itemcodeid = itm.itm_c_itemcodeid
WHERE
c.Comp_CompanyId = gcl.gcl_c_companyid
AND
itm.itm_c_itemcode IN (...) /* here provide list of one or more Item Codes to look for */
);
but I see there's a icl_c_companyid column in the ItemCode_Link so using GroupCode_Link table is not necessary?