Postgres Join 3 Tables(Timestamp) - sql

I have 3 tables and need mutliple values from them. I need pname(project), lead(project), author(changegroup) and updated(jiraissue)/created(changegroup). pname and lead are project name and leader of the project. Author is the one who changed the ticket the last time, and update and created are the timestamps from that action. But update and created are often not the same. So cant use them to filter. I have no problem to get pname, lead, and update. But I need the author too.
SELECT pname, lead, MAX(updated) FROM project join jiraissue on project.id=jiraissue.project GROUP BY(pname, lead);
That is the query command to get pname, lead, and updated. I filter the all tickets from a project, and look which was edited the most recently. I take that timestamp for the time the entire project was edited the last time. But couldn't create an command to get the author too. you help me?
Project Table:
The Project itself with project name and lead| public.id=jiraissue.project
Jira Issue Table:
jiraissues are all tickets from the projects |project.id=jiraissue.project, jiraissue.updated is most times changegroup.created, changegroup.issueid=jiraissue.id
Changegroup Table:
changegroup is a list of the times when a ticket is edited| changegroup.issueid=jiraissue.id, changegroup.created=jiraissue.updated

Your explanation left me confused. But here is my educated guess:
SELECT p.pname, p.lead, c.author, j.updated, c.created
FROM project p
LEFT JOIN (
SELECT DISTINCT ON (j.project)
j.project, j.updated, j.id
FROM jiraissue j
ORDER BY j.project, j.updated DESC NULLS LAST
) j ON j.project = p.id
LEFT JOIN changegroup c ON c.issueid = j.id;
Another case for DISTINCT ON. See:
Select first row in each GROUP BY group?
Eliminating unneeded rows before joining should be the fastest way.
I use 2x LEFT JOIN retain projects without any Jira issues in the result.

Related

SQL Count aggregate question, combining 3 tables

I am trying to join 3 tables to include only those employees who are assigned to more than one assignment. Through troubleshooting, I have found that my query works until I add my third table. Specifically, until I add the third table's columns to group by.
I need the third table added, as it included the start and end date of the projects.
I have been at this for days.
I have tried string_agg to bypass using the columns from the third table in the group by, but found that it it not supported in the program we're required to use.
I have tried different joins, different counts, using variables. I have tried joining the tables in different combinations and subsequently worked through other errors. I have tried to do nested select statements.
At this point, I have lost count. I started out with a cartesian product and have now worked out that I think the problem lies somewhere with grouping third(projects) table.
CREATE VIEW Assignments AS
SELECT a.EmpIDNumber,
COUNT(*) AS Frequency,
e.FirstName,
e.LastName,
a.PositionOnProject,
P.AssignedToProject AS ProjectName,
P.ProjectBeginDate AS StartDate,
P.FinishOnProject AS End_Date
FROM Assignments a
INNER JOIN Employees e ON a.EmpIDNumber = e.EmpIDNumber
INNER JOIN Projects p ON a.projectID = p.ProjectID
GROUP BY e.FirstName,
E.LastName,
a.PositionOnProject,
a.EmpIDNumber,
p.AssignedToProject,
p.ProjectBeginDate,
p.FinishOnProject
HAVING COUNT(*) > 1;
As is, I get no results. Just empty headers.
Removing the third table(projects) from the select and group by, I get the expected results, showing those employees who are assigned to more than one project.
I know I am doing something wrong and am open and eager to learn what that is. Any help in doing that is appreciated.
If you want project details for employees assigned to more than one project, then use window functions:
SELECT a.EmpIDNumber, a.Frequency,
e.FirstName, e.LastName, a.PositionOnProject,
P.AssignedToProject AS ProjectName,
P.ProjectBeginDate AS StartDate,
P.FinishOnProject AS End_Date
FROM (SELECT a.*, COUNT(*) OVER (PARTITION BY a.EmpIDNumber) as frequency
FROM Assignments a
) a INNER JOIN
Employees e
ON a.EmpIDNumber = e.EmpIDNumber INNER JOIN
Projects p
ON a.projectID = p.ProjectID
WHERE frequency > 1;
Your problem is that you have added the project information to the GROUP BY. Only one project is going to match those conditions, so the HAVNG clause ends up filtering everything out.

My question is about SQL, using a TOP function inside a sub-query in MS Access

Overall what I'm trying to achieve is a query that shows the most ordered item from a customer in a database. To achieve this I've tried making a query showing how many times a customer has ordered an item, and now I am trying to create a sub-query in it using TOP1 to discern the most bought items.
With the SQL from the first query (looking weird because I made it with the Access automatic creator):
SELECT
Customers.CustomerFirstName,
Customers.CustomerLastName,
Products.ProductName,
COUNT(SalesQuantity.ProductCode) AS CountOfProductCode
FROM (Employees
INNER JOIN (Customers
INNER JOIN Sales
ON Customers.CustomerCode = Sales.CustomerCode)
ON Employees.EmployeeCode = Sales.EmployeeCode)
INNER JOIN (Products
INNER JOIN SalesQuantity
ON Products.ProductCode = SalesQuantity.ProductCode)
ON Sales.SalesCode = SalesQuantity.SalesCode
GROUP BY
Customers.CustomerFirstName,
Customers.CustomerLastName,
Products.ProductName
ORDER BY
COUNT(SalesQuantity.ProductCode) DESC;
I have tried putting in a subquery after FROM line:
(SELECT TOP1 CountOfProduct(s)
FROM (.....)
ORDER by Count(SalesQuantity.ProductCode) DESC)
I'm just not sure what to put in for the "from"-every other tutorial has the data from an already created table, however this is from a query that is being made at the same time. Just messing around I've put "FROM" and then listed every table, as well as
FROM Count(SalesQuantity.ProductCode)
just because I've seen that in the order by from the other code, and assume that the query is discerning from this count. Both tries have ended with an error in the syntax of the "FROM" line.
I'm new to SQL so sorry if it's blatantly obvious, but any help would be greatly appreciated.
Thanks
As I understand, you want the most purchased product for each customer.
So, begin by building aggregate query that counts product purchases by customer (appears to be done in the posted image). Including customer ID in the query would simplify the next step which is to build another query with TOP N nested query.
Part of what complicates this is unique record identifier is lost because of aggregation. Have to use other fields from the aggregate query to provide unique identifier. Consider:
SELECT * FROM Query1 WHERE CustomerID & ProductName IN
(SELECT TOP 1 CustomerID & ProductName FROM Query1 AS Dupe
WHERE Dupe.CustomerID = Query1.CustomerID
ORDER BY Dupe.CustomerID, Dupe.CountOfProductCode DESC);
Overall what I'm trying to achieve is a query that shows the most ordered item from a customer in a database.
This answers your question. It does not modify your query which is only tangentially related.
SELECT s.CustomerCode, sq.ProductCode, SUM(sq.quantity) as qty
FROM Sales as s INNER JOIN
SalesQuantity as sq
ON s.SalesCode = sq.SalesCode
GROUP BY s.CustomerCode, sq.ProductCode;
To get the most ordered items, you can use this twice:
SELECT s.CustomerCode, sq.ProductCode, SUM(sq.quantity) as qty
FROM Sales as s INNER JOIN
SalesQuantity as sq
ON s.SalesCode = sq.SalesCode
GROUP BY s.CustomerCode, sq.ProductCode
HAVING sq.ProductCode IN (SELECT TOP 1 sq2.ProductCode
FROM Sales as s2 INNER JOIN
SalesQuantity as sq2
ON s2.SalesCode = sq2.SalesCode
WHERE s2.CustomerCode = s.CustomerCode
GROUP BY sq2.ProductCode
);
In almost any other database, this would be simpler, because you would be able to use window functions.

SQLite - Group by where more than x

I've got three tables which relate to support ticket data for a software development firm, the tables are arranged like so:
Tickets
[PK]
ID Ticket_Type Type Created Resolved
s-100 s Bug 1434725860524 1463075456304
d-29 d Deployment 1434724333500 1463665757667
p-50 p Upgrade 1434722686876 1466575675677
s-25 s Training Issue 1434723799989 1465675675677
P-ticket_links
[PK]
Pticket Link
p-50 s-100
p-50 s-102
p-50 d-29
D-ticket_servers
[PK]
ID Server
d-29 Live Server
d-30 Test Server
d-31 Live Server
The primary key columns in the bottom two tables are also foreign keys which reference the ID column of the Tickets table.
For each p ticket of Type 'Upgrade', I need to find out the number of linked s tickets which were created after the resolved date of the linked d ticket, which itself is of Type 'Deployment' and which was carried out against the Live Server.
I've written a query to get the total number of s tickets linked to each Upgrade p ticket using a GROUP BY clause:
SELECT *,count(ts.id)
from [P-ticket_links] ptls
inner join [Tickets] ts on ts.ID=ptls.Link
inner join [Tickets] ts2 on ts2.ID=ptls.Pticket
where ts.Ticket_Type='s'
and ts2.Type='Upgrade'
group by ptls.Pticket
I can also find the resolved date of the Live Server Deployment d ticket for each p ticket using a similar query. However, what I'm having trouble doing is joining those two results together in order to exclude s tickets which were created before the resolved date of the Live Server Deployment d ticket.
I've tried creating another alias of the Tickets table, filtering it to contain the relevant d-tickets and then putting in a clause like WHERE tickets1.created > tickets3.resolved, but that didn't give me the right results.
I think what I need to do is essentially return a table in which every every row contains one s ticket linked to the corresponding p ticket as well as the resolved date for the d ticket linked to that p ticket. I could change my database structure to include the information in the first instance, but I don't want to denormalise my database any more and I feel like I should be able to do this with SQL.
Can anyone point me to how I could achieve this?
I've figured it out. This is how to return the results that I want:
select *,count(*) from [p-ticket_links] ptls
inner join
(SELECT
ts2.id as 'p-id',
ts.resolved as 'd-resolved'
FROM [tickets] ts
inner join [p-ticket_links] ptl on [ptl].link=ts.id
inner join [d-ticket_servers] dts on dts.id=ts.id
inner join [tickets] ts2 on ptl.pticket=ts2.id
inner join [p-ticket_versions] ptvs on ptvs.id=ts2.id
where [ts].type='Deployment'
and dts.server='Live Server'
and ts.summary like '%upgrade%'
and ts2.project_type='Upgrade'
and ts.state <> 'Duplicate') dres on dres.[p-id]=ptls.pticket
inner join [tickets] ts on ts.id=ptls.link
inner join [tickets] ts2 on ts2.id=ptls.pticket
where ts.ticket_type='S'
and ts2.project_type='Upgrade'
and ts.created > dres.[d-resolved]
group by ptls.pticket

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

Getting records from three tables with sometimes unmatching fields

I have a question that should be easy to answer...
I have a table called Projects, primary key is ProjectId.
Second table is called ProjectResources, with ProjectId as a foreign key, plus fields for user and hours (represents the users assigned to work on the project)
Third table is TimesheetEntries (which the users use to record hours users actually worked on a project), with ProjectId as foreign Key, and field User
What is required is for me to show the records of the projectId,BudgetedHours (from ProjectResources table) and ActualHours (from the TimesheetEntries table); I would like however to include the following cases where:
a user was assigned to the project but did not work on it (in this case the budgeted hours should have a value and the actual hours should have zero)
a user was not assigned to the project but has nonetheless worked on it (in which case the BudgetedHours should be zero and the ActualHours should have a value)
a user was both assigned to the project and has worked on it (both BudgetedHours and ActualHours have values)
Could somebody direct me to a T-SQL statement to get this kind of result?
You could try something like:
SELECT p.ProjectId,
(CASE WHEN pr.[User] Is NULL THEN te.[User] ELSE pr.[User] END) as [User],
IsNull(pr.BudgetedHours, 0.0),
IsNull(Sum(te.ActualHours), 0.0)
FROM Project p
LEFT JOIN ProjectResources pr on p.ProjectId = pr.ProjectId
LEFT JOIN TimeSheetEntries te on p.p.ProjectId = te.ProjectId
GROUP BY p.ProjectId, te.User, pr.BudgetedHours
But I'm guessing at your field names, etc. so you would need to adapt this for your own domain.
I think the reason you are having problems is because you are thinking about the actual hours and the budgeted hours as being all essentially equal, because they are assigned to the project.
However, the actual and budgeted are calculated in very different ways. You need to calculate them using separate subqueries, as in the following example:
select coalesce(budget.ProjectId, actual.ProjectId) as ProjectId,
budget.BudgetedHours, actual.ActualHours
from
(
select projectid, sum(pr.hours) as BudgetedHours
from Projects p
left outer join ProjectResources pr
) budget
full outer join
(
select projectid, sum(tse.hours) as ActualHours
from Projects p
left outer join TimeSheetEntries tse
on tse.ProjectId = p.ProjectId
) actual
on budget.ProjectId = actual.ProjectId