Start Center Result Set for People Table - sql

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.

Related

How to distinguish these two ID requests when joining tables?

SQL noob here. I have a database of soccer matches that I am trying to learn/practice SQL with.
In one table (called "Match") there is the match_api_id, date, home_team_api_id, away_team_api_id, home_team_goal, away_team_goal.
In another table (called "Team") there is the team_api_id, team_long_name.
Right now I am trying to do a query to show the ID of the match, the date, the home team's name, and the away team's name.
SELECT M.match_api_id, M.date, T.team_long_name, T.team_long_name
FROM Match M
JOIN Team T ON (M.home_team_api_id = T.team_api_id)
JOIN Team T ON (M.away_team_api_id = T.team_api_id)
LIMIT 10
This code worked when I only used one join (the first one) to show the home team's name. However, when I add the second join it gives me the ambiguous column name error. How do I alter this code so that I can also display the away team's name?
YOu need different table aliases. Otherwise T is ambiguous:
SELECT M.match_api_id, M.date, TH.team_long_name, TA.team_long_name
FROM Match M JOIN
Team TH
ON M.home_team_api_id = TH.team_api_id JOIN
Team TA
ON M.away_team_api_id = TA.team_api_id;
LIMIT 10

MS Access One-to-Many Query

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.

SQL Query Display records only when value is missing

I am having an issue, I am new to SQL query work, but I have a query that runs and display employees and all their addresses history, but I have found that staff have been missing checking off the indicator for if the employee has mailing address. The addresses are stored in a table that has a reference to the employee id. How would I display results for a specific employee if no "2" value for mailing is found. The address table contains previous addresses and billing address flags, "1" and "3"?
In the addelement table
type_add_id|type_add_desc
1 |Billing
2 |Mailing
3 |Previous
Query
SELECT
addelement.type_add_desc
,address.street
,employee.name
FROM
address
INNER JOIN addelement
ON address.type_add_id = addelement.type_add_id
INNER JOIN employee
ON address.refid = employee.refid
order by employee.name
This will get you a list of employees that do not have a mailing address. Note that we start with all employees, outer join to the addresses, but constrain to not only match the employee, but also to be of the desired type of address. The WHERE clause then removes records from the resulting recordset where there is a value.
SELECT
employee.name
FROM
employee
LEFT OUTER JOIN address ON address.refid = employee.refid AND address.type_add_id = 2
WHERE
address.type_add_id IS NULL
Change the hardcoded integer in the JOIN to search out each of the desired types of addresses.
I think you should look at this http://sqlfiddle.com/#!9/e30116/1 and tell me what you think.
If the "2" is not there, it will simply give you the result of the other addresses.
Perhaps you'll make sense of this query easier than the one with a left join. It an also be confusing to understand why the filtering condition on the join must be with the join and not in the where clause. It'll be good for you to understand that eventually though if you continue learning SQL.
select *
from employee e
where not exists (
select 1
from address a
where a.refid = e.refid and a.type_add_id = 2
)
Many people seem to object to subqueries because their platforms don't optimize them well or because they see it as a crutch in using SQL. I suppose in a sense I am offering it here as an equivalent solution to help ramp up your understanding but either way I see nothing wrong with taking advantage of in and not in as a natural way of expression the solution.
This should return your employee #100 with all the addresses stored, even if employee has not address (any type).
select e.name, ad.type_add_desc, a.street
from employee e
left outer join address a on
e.refid = a.refid
left outer join addelement ad on
a.type_add_id = ad.type_add_id
where e.refid = 100
order by e.name;
To return rows that haven't a row relationship in other table you should use OUTER JOIN.

One to many relationships in T-SQL

I need to figure out how to find a certain group of records using T-SQL and I'm having trouble figuring out how I would need to create the WHERE clause to do this.
I have a SQL 2008 R2 system that I'm working with, and in this database there are a couple of tables. One contains personnel records, and another contains addresses. The addresses relate to the personnel records by a foreign key relationship. So for example, to get a list of all personnel and all of their associated addresses (a single person could have multiple addresses) I could write something like this:
SELECT id, name FROM personnel p
INNER JOIN address a
ON p.id = a.personnelid
However, each address has a column called isprimary, that is either 0 or 1. What I need to do is figure out how to find all personnel who do not have an associated address with isprimary set to 1. Or records that have no primary address.
Currently my thought is to build a temporary table with personnel who have addresses that aren't marked as primary. Then cycle through those and build a subset that have a primary address.
Then subtract the Personnel With Primary table from the results of Personnel With Non-Primary and I should have my list. However, I'm thinking that there has to be a more elegant way of doing this. Any ideas?
Try this, it should get all Personnel rows with no matching primary address:
SELECT *
FROM Personnel p
WHERE NOT EXISTS
(SELECT * FROM Address a WHERE a.personnelId = p.id AND a.isprimary = 1)
SELECT id, name FROM personnel p
INNER JOIN address a
ON p.id = a.personnelid
AND a.isprimary = 0
This ends up beeing a Left anti semi join pattern
and can be written like this:
SELECT id, name FROM personnel p
LEFT OUTER JOIN address a
ON p.id = a.personnelid
AND a.isprimary = 1
WHERE a.personnelId IS NULL
It can be interesting to test different ways because query plan are often not the same.

Needing 2 different ID's from the same ID Table

I am pulling reports for my company and am needing to pull a specific report that I am having trouble with. We are using SQL Server 2012 and I am pulling the SQL reports.
What I need is to pull a simple report:
Group Name, List of Members in the group; Supervisor of the group.
However, the problem is that the supervisor as well as the members and the group name all come from one table in order to get the relevant information. Currently here is my SQL code below:
Use DATABASE
go
-- This is the select portion deciding the columns needed.
select
C.group_name
,C2.first_name
,C2.last_name
-- These are the tables that the query is pulling from.
FROM db..groups AS G
LEFT OUTER JOIN db..contact AS C
ON G.group_id=C.contact_id
INNER JOIN db..contact AS C2
ON G.member=C2.contact_id
go
This pulls the first portion:
The group name, then the first name of a member in that group, and then the last name of a member in that group.
However, I am having trouble getting the supervisor portion. This portion uses the table db.contact under the column supervisor_id as a foreign key. The supervisor_id uses the same unique id as the normal contact_id, but in the same table. Some contact_ids have supervisor_id's that are other contact_id's from the same table, hence the foreign key.
How can I make it so I can get the contact_id that is equal to the supervisor_id of the contact_id that is equal to the group_id?
Taking a quick stab at this while we wait for details
You know you need groups and I'm assuming you don't care about Groups that have no members. Thus Groups INNER JOINed to Contact. This generates your direct group membership. To get the supervisor, you then need to factor in the Supervisor on the specific Contact row.
You might not have a boss, or your boss might be yourself. It's always interesting to see how various HR systems record this. In my example, I'm assuming the head reports to no one instead of themselves.
SELECT
G.group_name
, C.first_name
, C.last_name
-- this may produce nulls depending on outer vs inner join below
, CS.first_name AS supervisor_first_name
, CS.last_name AS supervisor_last_name
FROM
dbo.Groups AS G
INNER JOIN
dbo.Contact AS C
ON C.contact_id = G.member
LEFT OUTER JOIN
dbo.Contact AS CS
ON CS.contact_id = C.supervisor_id;
Depending on how exactly you wanted that data reported, there are various tricks we could use to report that data. In particular, GROUPING SETS might come in handy.
SQLFiddle