Created the formula but now have to break it up into years; there is a years column in original data seat with header for years - mysql-workbench

As title suggests, I created a result with a formula but now need to break it up into having the formula run for every "owner" but seperate the formula into years. I have the dates 2010-2019. Here is the code
SELECT * FROM finaltab;
Select finaltab.OWNER as OWNER, SUM(finaltab.shares) AS SSUM FROM finaltab WHERE trancode='S' GROUP BY OWNER Order by year;
Select finaltab.OWNER as OWNER, SUM(finaltab.shares) AS PSUM FROM finaltab WHERE trancode='P' GROUP BY OWNER Order by year;
SELECT finaltab.OWNER, SSUM, PSUM FROM
(SELECT finaltab.OWNER AS OWNER, SUM(finaltab.shares) AS SSUM FROM finaltab WHERE trancode='S' GROUP BY OWNER) AS STable
INNER JOIN
(SELECT finaltab.OWNER AS OWNER, SUM(finaltab.shares) AS PSUM FROM finaltab WHERE trancode='P' GROUP BY OWNER) aS PTable
ON (Stable.owner = Ptable.owner);
SELECT STable.OWNER, SSUM, PSUM, (PSUM - SSUM) / (PSUM + SSUM) as "IOF" FROM
(SELECT finaltab.OWNER as OWNER, SUM(finaltab.shares) AS SSUM From finaltab WHERE trancode='S' GROUP BY OWNER) AS STable
INNER JOIN
(SELECT finaltab.OWNER as OWNER, SUM(finaltab.shares) AS PSUM From finaltab WHERE trancode='P' GROUP BY OWNER) AS PTable
ON (STable.OWNER = PTable.OWNER);
Here is the table. Also I would like some direction on if I want to take the "IOF" or formula and implement it into a formula with absolute value for the "IOF" in the numerator. Thank you [1]: https://i.stack.imgur.com/P9GtU.png

Related

Selecting distinct values

The domain is:
company (id, name, adress)
employee (id, name, adress, company_id, expertise_id)
dependantrelative (id, name, employee_id)
expertise (id, name, class)
I want to know how to get the number of dependantrelatives of each employee who are unique experts in their respective companies.
The Query below does not return the correct answer. Can you help me?
SELECT DISTINCT dependantrelative.employee_id
, COUNT(*) AS qty_dependantrelatives
FROM dependantrelative
INNER JOIN employee
ON employee.id = dependantrelative.employee_id
GROUP BY dependantrelative.employee_id
I just tried out the Query below and it works, but I want to know if there is a faster and simple way of getting the answer.
SELECT employee.id
,COUNT(dependantrelative.employee_id) AS qty_dependantrelatives
FROM (
SELECT employee.company_id
, employee.expertise_id AS expert
, COUNT(employee.expertise_id)
FROM employee
GROUP BY employee.company_id
, employee.expertise_id
HAVING COUNT(employee.expertise_id)<2
) AS uniexpert
LEFT JOIN employee
ON employee.expertise_id = uniexpert.expert
LEFT JOIN salesorderdetail
ON dependantrelative.employee_id = employee.id
GROUP BY employee.id
ORDER BY employee.id

find all companies where all employees in specific state

I have a table employees with columns:
company_id,
id,
opt_state (ceased_membership, ignition, opted_out, opted_in),
opt_out_on.
I want to query all companies where all employees opt-state is in ('ceased_membership', 'ignition', 'opted_out') and the date opt_out_on when last employee left.
I have tried this but it didn't work
select company_id from employees where id=all(select id from
employees
where opt_state in ('ceased_membership', 'ignition','opted_out')
Then I wrote this query below, which worked very well and gave me the resolution I was looking for. However, I'd like to ask here if this can be done differently, more elegantly.
SELECT
e.company_id
, max_opt_out
FROM (
SELECT DISTINCT
company_id
, count(id)
OVER (
PARTITION BY company_id ) opt_out
FROM employees
WHERE opt_state IN ('ceased_membership', 'ignition', 'opted_out')) e
LEFT JOIN (
SELECT
company_id
, count(id) opt_in
, max(opt_out_on) max_opt_out
FROM employees
GROUP BY company_id) S
ON e.company_id = s.company_id
WHERE e.opt_out = s.opt_in;
This seems like a good time to use the HAVING clause
SELECT company_id, max(opt_out_on)
FROM employees e
GROUP BY company_id
HAVING bool_and( opt_state in ('ceased_membership', 'ignition','opted_out'));
HAVING in a bit like a WHERE but the condition apples to whole GROUPS
bool_and is an agregate function that is only true when all the records in the group are result in true.
I'd say that you want to query a maximum out_out_on for each company that only have employees in a set of states, which means that do not have any employee not in a set of states.
So, translated to SQL:
select company_id, max(opt_out_on)
from employees e
where not exists(
select 1 from employees
where company_id=e.company_id
and opt_state not in ('ceased_membership', 'ignition','opted_out')
)
group by company_id;

Query-Sql Developer

I am creating some queries for my project, but I face some difficulties with the follow ones:
A SELECT statement containing a subquery to retrieve a list of Locations (location id and street_address) that have employees with higher salary than the average of their department. The list must contain the number of those employees and their total salary per location. Name these aggregates respectively "emp" and "totalsalary". The locations in the list must be ordered by location_id.
Select LOCATION_ID, STREET_ADDRESS
from HR.LOCATIONS IN
(Select Employee_id
from HR.Employees
Where Salary > round(avg(SALARY)))
order by location_id;
error: SQL command not properly ended
and the second query is the following
The JOB_HISTORY table can contain more than one entries for an employee who was hired more than once. Create a query to retrieve a list of Employees that were hired more than once. Include the columns EMPLOYEE_ID, LAST_NAME, FIRST_NAME and the aggregate "Times Hired".
SELECT FIRST_NAME,LAST_NAME,EMPLOYEE_ID,
count (*)as TIMES_HIRED
from HR.JOB_HISTORY, HR.EMPLOYEES
where EMPLOYEE_ID= LAST_NAME
having COUNT(*) >1;
error: not a single-group
Try these hope they help. I am making an assumption that employee table has Location_Id column. I am adding Employee_id to Group by to make sure you get correct TotalSalary:
Select LOCATION_ID, STREET_ADDRESS, Count(Employee_id) AS emp, SUM(salary) AS totalsalary
from HR.LOCATIONS INNER JOIN
(Select Employee_id, salary
from HR.Employees
Having Salary > round(avg(SALARY), 0)) AS Emp ON HR.LOCATION_ID = Emp.Location_ID
Group By LOCATION_ID, STREET_ADDRESS, Employee_id
order by location_id;
For the second question:
SELECT FIRST_NAME,LAST_NAME,EMPLOYEE_ID,
count(Employee_id) as TIMES_HIRED
from HR.JOB_HISTORY inner join HR.EMPLOYEES On JOB_HISTORY.Employee_id = Employees.Employee_id
Group By FIRST_NAME,LAST_NAME,EMPLOYEE_ID
Having count(Employee_id) >1;

How to get fields and added in group by in PostreSQL8.4?

I am selecting column used in group by and count, and query looks something like
SELECT s.country, count(*) AS posts_ct
FROM store s
JOIN store_post_map sp ON sp.store_id = s.id
GROUP BY 1;
However, I want to select some more fields, like store name or store address from store table where count is max, but I don't to include that in group by clause.
For instance, to get the stores with the highest post-count per country:
SELECT DISTINCT ON (s.country)
s.country, s.store_id, s.name, sp.post_ct
FROM store s
JOIN (
SELECT store_id, count(*) AS post_ct
FROM store_post_map
GROUP BY store_id
) sp ON sp.store_id = s.id
ORDER BY s.country, sp.post_ct DESC
Add any number of columns from store to the SELECT list.
Details about this query style in this related answer:
Select first row in each GROUP BY group?
Reply to comment
This produces the count per country and picks (one of) the store(s) with the highest post-count:
SELECT DISTINCT ON (s.country)
s.country, s.store_id, s.name
,sum(post_ct) OVER (PARTITION BY s.country) AS post_ct_for_country
FROM store s
JOIN (
SELECT store_id, count(*) AS post_ct
FROM store_post_map
GROUP BY store_id
) sp ON sp.store_id = s.id
ORDER BY s.country, sp.post_ct DESC;
This works because the window function sum() is applied before DISTINCT ON per definition.

Difficult query (DB2)

Suppose I have a table called spitems with the following fields:
spitemid (unique key)
modifiedon (timestamp)
parentid
a number of other unsignificant fields
What I want to retrieve, is the spitem rows with the highest modifiedon day for each parentid.
However, be aware that the modifiedon timestamp is not unique, so it is possible that for one parent id, there are two spitemids with the same modifiedon timestamp. In that case, I need one of these two spitemids listed, I don't care which one.
So to be clear: the list I return should contain all the parentids once and only once.
update
meeting over, here is my shot:
select *
from table
join where spitmid in
(select max(spitmid)
from table
join
(select parentid, max(modifiedon) as d from table group by parentid) inlist
on table.parentid = inlist.parentid and table.modifiedon = inlist.d
group by parentid, datemodified
)
old entry
not sure if this is different on DB2, here it is for sql server.
select *
from table
join (select parentid, max(modifiedon) as d from table group by parentid) as toplist on
table.parentid = toplist.parentid and table.modifiedon = toplist.d
hmm... this will return more than one for the dups... can't fix it now, have to go to a meeting.
Based on your requirements, following should get you the latest items.
SELECT t1.*
FROM Table t1
INNER JOIN (
SELECT spitemid = MAX(t1.spitemid)
FROM Table t1
INNER JOIN (
SELECT parentid, modifiedon = MAX(modifiedon)
FROM Table
GROUP BY parentid
) t2 ON t2.parentid = t1.parentid
AND t2.modifiedon = t1.modifiedon
GROUP BY t1.parentid, t1.modifiedon
) t2 ON t2.spitemid = t1.spitemid
You can do it with two nested subqueries. The first gets max modifiedon for each parentid, and then the second gets max spitemid for each parentid/modifiedon group.
SELECT *
FROM spitems
WHERE spitemid IN
(
SELECT parentid, modifiedon, max(spitemid) spitemid
FROM (
SELECT parentid, MAX(modifiedon) modifiedon
FROM spitems
GROUP BY parentid
) A
GROUP BY parentid, modifiedon
)
A common table expression will give you the opportunity to number the rows before you issue the final SELECT.
WITH items AS
(
SELECT spitemid, parentid, modifiedon,
ROWNUMBER() OVER (PARTITION BY parentid ORDER BY modifiedon DESC) AS rnum
FROM yourTable
)
SELECT spitemid, parentid, modifiedon FROM items WHERE rnum = 1
;
SELECT sr.receiving_id, sc.collection_id FROM stock_collection as sc, stock_requisation as srq, stock_receiving as sr WHERE (sc.stock_id = '" & strStockID & "' AND sc.datemm_issued = '" & strMM & "' AND sc.qty_issued >= 0 AND sc.collection_id = srq.requisition_id AND srq.active_status = 'Active') OR (sr.stock_id = '" & strStockID & "' AND sr.datemm_received = '" & strMM & "' AND sr.qty_received >= 0)