I am stuck with a query and would appreciate if you guys could help me.
We are using a table (MS Access) to store project plans for multiple companies as follows:
ID PROJECT_NAME COMPANY_NAME MILESTONE_NAME MILESTONE_TYPE
The objective of my query is to return the count of "applicable" rollouts.
A rollout is the unique combination of project and company. Example:
Project 1 being executed in the Company A
Project 2 being executed in the Company A
Project 1 being executed in the Company B
An applicable project is whatever project which it last milestone has a MILESTONE_TYPE different than "DUMMY".
An applicable rollout should look like this:
ID PROJECT_NAME COMPANY_NAME MILESTONE_NAME MILESTONE_TYPE
1 Project 3 Company D 6.2 Rollout Completed Applicable
In order to retrieve the last milestone of the project I am using the following SQL:
SELECT Sheet1.[PROJECT_NAME], MAX(Sheet1.[MILESTONE_NAME])
FROM Sheet1
INNER JOIN Sheet1 AS Sheet1_1 ON (Sheet1.[PROJECT_NAME] = Sheet1_1.[PROJECT_NAME])
AND (Sheet1.[MILESTONE_NAME] = Sheet1_1.[MILESTONE_NAME])
GROUP BY Sheet1.[PROJECT_NAME]
ORDER BY Sheet1.[PROJECT_NAME]
The expected result of the query I need your support would be:
PROJECT_NAME COUNT_OF_APPLICABLE_ROLLOUTS
Project A 5
Project B 6
However I have absolutely no idea how to even get started...
Does anyone know how to put in all in a SQL query?
Thanks in advance.
Assuming that bigger "id" means later, the following query returns information about the latest non-dummy row:
select p.*
from Sheet1.p join
(select project_name, company_name, max(id) as maxid
from Sheet1
where Milestone_Name <> 'Dummy'
group by project_name, company_name
) pc
on p.project_name, pc.company_name
(Note: I haven't tested this so it might have syntax errors.)
You can try this:
SELECT myTable.*
FROM (
SELECT DISTINCT COMPANY_NAME
FROM Sheet1
) CN
CROSS APPLY
(
SELECT TOP 1 *
FROM Sheet1 myTable2
WHERE myTable2.COMPANY_NAME = CN.COMPANY_NAME
ORDER BY
MILESTONE_NAME DESC
) myTable
Related
I have run into an issue I don't know how to solve. I'm working with a MS Access DB.
I have this data:
I want to write a SELECT statement, that gives the following result:
For each combination of Project and Invoice, I want to return the record containing the maximum date, conditional on all records for that combination of Project and Invoice being Signed (i.e. Signed or Date column not empty).
In my head, first I would sort the irrelevant records out, and then return the max date for the remaining records. I'm stuck on the first part.
Could anyone point me in the right direction?
Thanks,
Hulu
Start with an initial query which fetches the combinations of Project, Invoice, Date from the rows you want returned by your final query.
SELECT
y0.Project,
y0.Invoice,
Max(y0.Date) AS MaxOfDate
FROM YourTable AS y0
GROUP BY y0.Project, y0.Invoice
HAVING Sum(IIf(y0.Signed Is Null,1,0))=0;
The HAVING clause discards any Project/Invoice groups which include a row with a Null in the Signed column.
If you save that query as qryTargetRows, you can then join it back to your original table to select the matching rows.
SELECT
y1.Project,
y1.Invoice,
y1.Desc,
y1.Value,
y1.Signed,
y1.Date
FROM
YourTable AS y1
INNER JOIN qryTargetRows AS sub
ON (y1.Project = sub.Project)
AND (y1.Invoice = sub.Invoice)
AND (y1.Date = sub.MaxOfDate);
Or you can do it without the saved query by directly including its SQL as a subquery.
SELECT
y1.Project,
y1.Invoice,
y1.Desc,
y1.Value,
y1.Signed,
y1.Date
FROM
YourTable AS y1
INNER JOIN
(
SELECT y0.Project, y0.Invoice, Max(y0.Date) AS MaxOfDate
FROM YourTable AS y0
GROUP BY y0.Project, y0.Invoice
HAVING Sum(IIf(y0.Signed Is Null,1,0))=0
) AS sub
ON (y1.Project = sub.Project)
AND (y1.Invoice = sub.Invoice)
AND (y1.Date = sub.MaxOfDate);
Write A SQL query, which should be possible in MS-Access too, like this:
SELECT
Project,
Invoice,
MIN([Desc]) Descriptions,
SUM(Value) Value,
MIN(Signed) Signed,
MAX([Date]) "Date"
FROM data
WHERE Signed<>'' AND [Date]<>''
GROUP BY
Project,
Invoice
output:
Project
Invoice
Descriptions
Value
Signed
Date
A
1
Ball
100
J.D.
2022-09-20
B
1
Sofa
300
J.D.
2022-09-22
B
2
Desk
100
J.D.
2022-09-23
Note: for invoice 1 on project A, you will see a value of 300, which is the total for that invoice (when grouping on Project='A' and Invoice=1).
Maybe I should have used DCONCAT (see: Concatenation in between records in Access Query ) for the Description, to include 'TV' in it. But I am unable to test that so I am only referring to this answer.
Try joining a second query:
Select *
From YourTable As T
Inner Join
(Select Project, Invoice, Max([Date]) As MaxDate
From YourTable
Group By Project, Invoice) As S
On T.Project = S.Project And T.Invoice = S.Invoice And T.Date = S.MaxDate
For the sake of simplicity, let’s assume that the table in question is called app and it has only three fields:
Person_id | employee_id | appointment_time
----------+-------------+-----------------
int | int | date
The table holds details of all medical appointments, past and future, for all clients (person_id) and specialists (employee_id).
What I am trying to figure out is how to create a list of appointments for a given specialist (let's say with an id of 235) and their corresponding "referals" (if any) - the previous appointment for a given person_id with an earlier date and serviced by another specialist (id <> 235).
SELECT
qLast.person_id,
qLast.employee_id,
qLast.LastDate,
qPrevious.employee_id,
qPrevious.PreviousDate
FROM
(
SELECT
app.person_id,
app.employee_id,
Max(app.appointment_time) AS LastDate
FROM
app
GROUP BY
app.person_id,
app.employee_id
HAVING
app.person_id <> 0
AND app.employee_id = 235
) qLast
LEFT JOIN (
SELECT
qSub.person_id,
app.employee_id,
qSub.MaxOfappointment_time AS PreviousDate
FROM
(
SELECT
app.person_id,
Max(app.appointment_time) AS MaxOfappointment_time
FROM
app
GROUP BY
app.person_id,
app.employee_id
HAVING
app.person_id <> 0
AND app.employee_id <> 235
) qSub
INNER JOIN app ON (
qSub.MaxOfappointment_time = app.appointment_time
)
AND (qSub.person_id = app.person_id)
) qPrevious ON qLast.person_id = qPrevious.person_id;
My mangled attempt almost works but sadly falls on its confused face when there is an appointment for a specialist with id<>235 with a later date than the last appointment for id=235. For now I run another query on the results of this one to filter out the unwanted records but it a rather ugly kludge. I'm sure there is a better and more elegant way of solving it. Help please!
I think you basically want lag(), but that is not available in SQL Server 2008 (time to upgrade to supported software!).
You can use apply instead:
select a.*, a2.*
from app a cross apply
(select top (1) a2.*
from app a2
where a2.person_id = a.person_id and
a2.employee_id <> a.employee_id and
a2.appointment_time < a.appointment_time
order by a2.appointment_time desc
) a2
I'm stuck on a problem where I am creating a report and need to show records which have two or more bank accounts (some of our employees are international and get paid in more than one currency).
The report I created brings back all employees and their bank account information. However, I want this report only to bring back employees with 2 or more bank accounts.
Here is some test data below:
As you can see, Gareth has more than one bank account - what filter can I write to just bring back his record?
Assuming it is mysql, sqlite and even postgresql (I think). it should be
SELECT * FROM table_name WHERE "First Name" = "Gareth";
However if you are using the MySQL binding for excel be sure that "Gareth" is listed for each account he owns. It may look cleaner but SQL will interpret the row beneath "Gareth" as "". Doing this will also mean you will need a new index, "First Name" can't be set as "UNIQUE". Also having spaces in columns is pretty ugly SQL syntax best to use camelCase or under_scores.
Assuming Person_Number as the primary key of the table accounts
SELECT * FROM accounts WHERE accounts.First_Name in
(SELECT a.First_Name
FROM accounts a
INNER JOIN accounts b
ON a.Person_Number = b.Person_Number
WHERE a.First_Name = b.First_Name
AND a.Bank_Account_Name <> b.Bank_Account_Name
);
Try this if you are using database like oracle, sqlserver....
select b1.* from account_info_table b1 where exists (select 1 from account_info_table b2 where b1.first_name=b2.first_name group by b2.first_name having count(*)>2);
or
select * from account_info_table where first_name in (select first_name from account_info_table group by first_name having count(*)>2);
Use This Code :
;WITH _CTE AS
(
SELECT *,ROW_NUMBER()OVER(PARTITION BY FirstName Order By FirstName)ROWNO FROM #Temp
)SELECT FirstName,BankAccountName,BankBranchName,BankAccountNo,SortCode FROM _CTE WHERE ROWNO > 1
select empleado from empleados
group by empleado
having count(*) > 1
I am using Oracle. I have table like:
Company Employee salary
A1 Jim 122000
...
I want to return the company with the highest number of employee whose salary is above 2 standard deviations (~>95%). Here is my code
With Com_2Std as (
Select company-name, AVG(salary)+2*STDDEV(salary) as AboveS
From works
Group By company-name)
Select company-name, count(employee-name) as ENumber
From works
Where ENumber=MAX(
Select count(a.employee-name)
From works a, Com_2Std b
Where a.company-name=b.company-name
And a.salary>b.AboveS;
Group by a.company-name)
Group by company-name;
I have two quesions:
(1) I can't access to oracle today and can't test it. Is my code correct please?
(2) It looks quite complicated, any way to simplify it please?
with Com_2Std as (
select company-name, AVG(salary)+2*STDDEV(salary) as AboveS
from works
group by company-name
),
CompanyCount as (
select a.company-name, count(*) as CountAboveS
from
works a
inner join Com_2Std b on a.company-name=b.company-name
where
a.salary > b.AboveS
group by a.company-name
)
select company-name
from CompanyCount
where CountAboveS = (select max(CountAboveS) from CompanyCount)
This ought to be close. It will produce ties as well.
I'm trying to do this update but for some reason I cannot quite master SQL sub queries.
My table structure is as follows:
id fk date activeFlg
--- -- ------- ---------
1 1 04/10/11 0
2 1 02/05/99 0
3 2 09/10/11 0
4 3 11/28/11 0
5 3 12/25/98 0
Ideally I would like to set the activeFlg to 1 for all of the distinct foreign keys with the most recent date. For instance after running my query id 1,3 and 4 will have an active flag set to one.
The closest thing I came up with was a query returning all of the max dates for each distinct fk:
SELECT MAX(date)
FROM table
GROUP BY fk
But since I cant even come up with the subquery there is no way I can proceed :/
Can somebody please give me some insight on this. I'm trying to really learn more about sub queries so an explanation would be greatly appreciated.
Thank you!
You need to select the fk to and then restrict by that, so
SELECT fk,MAX(date)
FROM table
GROUP BY fk
To
With Ones2update AS
(
SELECT fk,MAX(date)
FROM table
GROUP BY fk
)
Update table
set Active=1
from table t
join Ones2update u ON t.fk = u.fk and t.date = u.date
also I would test first so do this query first
With Ones2update AS
(
SELECT fk,MAX(date)
FROM table
GROUP BY fk
)
selct fk, date, active
from table t
join Ones2update u ON t.fk = u.fk and t.date = u.date
to make sure you are getting what you expect and I did not make any typos.
Additional note: I use a join instead of a sub-query -- they are logically the same but I always find joins to be clearer (once I got used to using joins). Depending on the optimizer they can be faster.
This is the general idea. You can flesh out the details.
update t
set activeFlg = 1
from yourTable t
join (
select id, max([date] maxdate
from TheForeignKeyTable
group by [date]
) sq on t.fk = sq.id and t.[date] = maxdate