MS Access One-to-Many Query - sql

I'm working on a service type database. Customers can have many equipment types and many service calls.
I'm trying to make a query that selects the customers name, address, etc when certain parameters are met with relation to the equipment types.
A customer can have upto 5 different equipment types. Some only have 1, some have all 5.
My query is trying to find customers with equipment type 3 installed, but not equipment type 5. The equipment type 3 must also have a service date between to date fields on my search form.
I'm drawing a blank when it comes to writing this query. I was able to query the customers with equipment type 3 and specific service dates, but I can't seem to be able to eliminate the customers that also have equipment 5 installed, even if they also have equipment type 3 installed.
This is my SQL:
SELECT
tblCustomers.WCWF_ID,
tblCustomers.CustBusiness,
tblCustomers.CustLastName,
tblCustomers.CustFirstName,
tblCustomers.CustAddress,
tblCustomers.CustCity,
tblCustomers.CustST,
tblCustomers.CustZip5,
tblEquip.EquipResinDate,
tblEquip.EquipType,
tblCustomers.CustPostCard
FROM
tblCustomers
INNER JOIN
tblEquip ON tblCustomers.WCWF_ID = tblEquip.WCWF_ID
WHERE
(((tblEquip.EquipResinDate) Between [forms]![MailSearchSelect]![StartDate] And [forms]![MailSearchSelect]![EndDate])
AND ((tblEquip.EquipType)=3
AND (tblEquip.EquipType)<>5)
AND ((tblCustomers.CustPostCard)=True));
Any help would be greatly appreciated.

The problem with your query is that you are tying to use a single JOIN to filter in customers with equipment type 3 and filter out customers with equipment type 5 : you would need to split that logic into two distinct parts.
To pull out customers that have equipment type 3 installed, using a JOIN is fine (I just moved the related conditions from the WHERE clause to the JOIN, for more clarity). It would also have been possible to express this requirement as a WHERE EXISTS condition with a correlated subquery.
To exclude customers that have equipment type 5 installed, you can either :
use a NOT EXISTS condition in the WHERE clause with a correlated subquery (I chose that option)
or use a LEFT JOIN with WHERE ... IS NULL.
Query :
SELECT
c.WCWF_ID,
c.CustBusiness,
c.CustLastName,
c.CustFirstName,
c.CustAddress,
c.CustCity,
c.CustST,
c.CustZip5,
e.EquipResinDate,
c.EquipType,
c.CustPostCard
FROM
tblCustomers AS c
INNER JOIN tblEquip AS e
ON e.WCWF_ID = c.WCWF_ID
AND e.EquipType = 3
AND e.EquipResinDate
BETWEEN [forms]![MailSearchSelect]![StartDate]
AND [forms]![MailSearchSelect]![EndDate])
WHERE
c.CustPostCard = True
AND NOT EXISTS (
SELECT 1
FROM tblEquip AS e2
WHERE
e2.WCWF_ID = c.WCWF_ID
AND e2.EquipType = 5
)
PS : it is also a good idea to give alias to the table names ; it makes the query more readable and may avoid subtle bugs caused by name clashes when the same table is referenced more than once in the query.

Related

How to query 2 different schema tables with different column name same information in postgresql

When I query I do not get match list side by side and database reference fails, why?
I tried using one connection and two different schemas, first schema name table has same reference details with second table column, and I would like to compare side by side what equals exactly from rw.reference table 1, with table 2 qt.ref_number because they should match between both. I only get output data from top first query with rd.reference and second table does not list anything with, qt.ref_number, why postgresql does not cross database reference?
Query:
Select distinct
rd.reference,
region1_scorecard
From local_dev.user.rawdata rd
Inner join customerid as id
on rd.site=id.site
union all
Select distinct
qt.ref_number,
region2_decision
From local_dev.account.quote qt
Inner join rep_id id
on qt.application=id.application
Order by rd.reference

SQL refusing to do a join even when every identifier is valid? (ORA-00904)

Made this account just to ask about this question after being unable to find/expending the local resources I have, so I come to you all.
I'm trying to join two tables - ORDERS and CUSTOMER - as per a question on my assignment
For every order, list the order number and order date along with the customer number, last name, and first name of the customer who placed the order.
So I'm looking for the order number, date, customer number, and the full name of customers.
The code goes as such
SELECT ORDERS.ORDR_ORDER_NUMBER, ORDERS.ORDR_ORDER_DATE, ORDERS.ORDR_CUSTOMER_NUMBER, CUSTOMER.CUST_LAST, CUSTOMER.CUST_FIRST
FROM ORDERS, CUSTOMER
WHERE ORDERS.ORDR_CUSTOMER_NUMBER = CUSTOMER.CUST_CUSTOMER_NUMBER;
I've done this code without the table identifiers, putting quotation marks around ORDERS.ORDR_CUSTOMER_NUMBER, aliases for the two tables, and even putting a space after ORDR_ in both SELECT & WHERE for laughs and nothing's working. All of them keep coming up with the error in the title (ORA-00904), saying [ORDERS.]ORDR_CUSTOMER_NUMBER is the invalid identifier even though it shouldn't be.
Here also are the tables I'm working with, in case that context is needed for help.
Anyway, the query that produces the result you want should take the form:
select
o.ordr_order_number,
o.ordr_order_date,
c.cust_customer_number,
c.cust_last,
c.cust_first
from orders o
join customer c on c.cust_customer_number = o.ordr_customer_number
As you see the query becomes a lot easier to read and write if you use modern join syntax, and if you use table aliases (o and c).
You have to add JOIN or INNER JOIN to your query. Because the data comes from two different tables the WHERE clause will not select both.
FROM Orders INNER JOIN Customers ON Orders.order_Customer_Number = Customer.Cust_Customer_Number

MS Access SQL Query merging two different fields from separate tables shows reference ID's instead of actual values

I have two separate tables in my access database, which both use a third table as the reference for one particular field on each table. The data is entered onto the different tables by separate forms. Then I have several queries that then reference those particular fields that count and show unique values. Those queries show the actual values, then I created an sql query that does the same thing, only it shows the reference ID instead of the value in the actual field.
table ODI----------table CDN----------reference table
id RHA---------id CHA----------------id HA
1 blank----------1 radio---------------1 internet
2 internet-------2 tv------------------2 radio
3 referral-------3 radio---------------3 referral
4 tv-------------4 blank---------------4 repeat customer
5 blank----------5 internet------------5 tv
6 internet-------6 referral------------6 employee
7 referral-------7 referral------------7 social media
this is the code I am trying to make work.
SELECT m.[Marketing Results], Count(*) AS [Count]
FROM (SELECT RHA as [Marketing Results] FROM ODI
UNION ALL
SELECT CHA as [Marketing Results] FROM CDN) AS m
GROUP BY m.[Marketing Results]
HAVING (((m.[Marketing Results]) Is Not Null))
ORDER BY Count(*) DESC;
and what my desired result is,
Marketing Results--Counts
referral------------------4
internet------------------3
radio---------------------2
tv------------------------2
Lookup fields with alias don't show what is actually stored in table. ID is stored, not descriptive alias. Lookup alias will carry into regular queries but Union query only pulls actual stored values. At some point need to include reference table in query by joining on key fields in order to retrieve descriptive alias. Options:
in each UNION query SELECT line, join tables
join UNION query to reference table
join aggregate query to reference table
Most experienced developers will not build lookups in table because of confusion they cause. Also, they are not portable to other database platforms. http://access.mvps.org/Access/lookupfields.htm

Start Center Result Set for People Table

I am working with the Maximo Asset Management System (version 7.1.1.6). I am trying to display a result set on the start center that contains a Do Not Call list of specific people. However, when using a query for the result set (a query that was saved in the People section that contains the appropriate "where" clause such as "department='ABC'"), I cannot select the phone number or the email address as a column to display. I believe this is due to the fact that the "Primary Phone" and "Primary Email" fields in the person table are not really there. They are virtual fields that are connected in the People application to the Phone and Email tables and joined on the personid column. If I run the following query in the database, I get the result set that I want:
select * from dbo.person as p
left outer join dbo.phone as ph on p.personid=ph.personid and ph.isprimary=1
left outer join dbo.email as e on p.personid=e.personid and e.isprimary=1
Unfortunately for the result sets, you don't have access to the "FROM" clause you can only edit the "WHERE" clause.
Anyone have any idea how to solve this other than adding 2 new columns to the person table for primary phone and primary email? I don't want to HAVE to do it, but I can if I must.
How about this for a where clause
... where (select count(*) from dbo.phone ph where :personid = ph.personid and ph.isprimary=1) > 0 and (select count(*) from dbo.email e where :personid = e.personid and e.isprimary=1) > 0
I can also think of a solution creating a relationships in the database configuration application, but the above query is more straight forward.

Select based on the number of appearances of an id in another table

I have a table B with cids and cities. I also have a table C that has these cids with extra information. I want to list all the cids in table C that are associated with ALL appearances of a given city in Table B.
My current solution relies on counting the number of times the given city appears in Table B and selecting only the cids that appear that many times. I don't know all the SQL syntax yet, but is there a way to select for this kind of pattern?
My current solution:
SELECT Agents.aid
FROM Agents, Customers, Orders
WHERE (Customers.city='Duluth')
AND (Agents.aid = Orders.aid)
AND (Customers.cid = Orders.cid)
GROUP BY Agents.aid
HAVING count(Agents.aid) > 1
It only works because I know right now with the HAVING statement.
Thanks for the help. I wasn't sure how to google this problem, since it's pretty specific.
EDIT: I'm pinpointing my problem a bit. I need to know how to determine if EVERY row in a table has a certain value for a field. Declaring a variable and counting the rows in a sub-selection and filtering out my results by IDs that appear that many times works, but It's really ugly.
There HAS to be a way to do this without explicitly count()ing rows. I hope.
Not an answer to your question, but a general improvement.
I'd recommend using JOIN syntax to join your tables together.
This would change your query to be:
SELECT Agents.aid
FROM Agents
INNER JOIN Orders
ON Agents.aid = Orders.aid
INNER JOIN Customers
ON Customers.cid = Orders.cid
WHERE Customers.city='Duluth'
GROUP BY Agents.aid
HAVING count(Agents.aid) > 1
What variant of SQL are you using?
To start with, you can (and should) use JOIN instead of doing it in the WHERE clause, e.g.,
select Agents.aid
from Agents
join Orders on Agents.aid = Orders.aid
join Customers on Customers.cid = Orders.cid
where Customers.city = 'Duluth'
group by Agents.aid
having count(Agents.aid) > 1
After that, I'm afraid I might be a little lost. Using the table names in your example query, what (in English, not pseudocode) are you trying to retrieve? For example, I think your sample query is retrieving the PK for all Agents that have been involved in at least 2 Orders involving Customers in Duluth.
Also, some table definitions for Agents, Orders, and Customers might help (then again, they might be irrelevant).
I'm not sure if I understood you problem, but I think the following query is what you want:
SELECT *
FROM customers b
INNER JOIN orders c USING (cid)
WHERE b.city = 'Duluth'
AND NOT EXISTS (SELECT 1
FROM customers b2
WHERE b2.city = b.city
AND b2.cid <> cid);
Probably you will need some indexes on these columns.