Find most recent date - postgresql

I have o table name table_1 with 4 columns id, text, fromDate, toDate. The table represents the working experience.I want to create a function which will return the row with columns id, text where the employee worked more recently. This means I need column toDate to be closest to today.
Here is a demonstration of my code:
Select (abs("toDate"-now())) as date_diff
from table_1
Select id,text
from table_1
where (abs("toDate"-now()))=select min(date_diff)
Is this correct or is there something better I can do?

I wil try something like this:
Select id,text
from table_1
where "toDate" = ( select max ("toDate") from table_1 )
It will provide you the latest "toDate" value.

Try this:
select * from table_1
order by to_date desc
limit 1

Related

Why is this nested INNER JOIN not working in POSTGRESQL?

I am using the Nothwind data base & working in pgAdmin, and my query is looking like this at the moment
SELECT
TO_CHAR (o.ShippedDate, 'yyyy.MM') AS Month
,o.OrderID
,Total
,SUM (Total) OVER PARTITION BY TO_CHAR (ShippedDate,
‘yyyy.MM’) ORDER BY O.OrderID) AS Running_Total
FROM public.orders O
INNER JOIN (
SELECT OrderID, SUM(Quantity*UnitPrice) AS Total
FROM public.order_details
GROUP BY OrderID
ORDER BY OrderID
) OD ON O.OrderID = OD.OrderID
WHERE
TO_CHAR (o.ShippedDate, 'yyyy.MM') IS NOT NULL
And is is not working, it says:
ERROR: column "o.shippeddate" must appear in the GROUP BY clause or be used in an aggregate function
LINE 2: TO_CHAR (o.ShippedDate, 'yyyy.MM') AS Month
Can you help me out what could be the issue? Thanks!
I fixed the query, so it is now the correct one.

Update column with more than one value

I have a table tableA which looks something like this:
issue_id start_date end_date
issue1 2019-11-07 2020-04-30
issue2 2019-11-07 2020-01-28
I have to update the end_date based on the results of the query.
UPDATE tableA SET end_date =
(
SELECT max_end_date from update_end_date
)
WHERE issue_id = (SELECT issue_id FROM update_end_date);
It works when when query returns one result. However it fails when more than one results are returned which make sense. I cannot pre determine the results of the query so it might return more than one result. Is there any way if I can update the column with multiple values.
You could use correlated subquery:
UPDATE tableA
SET end_date = (SELECT max_end_date
from update_end_date
WHERE update_end_date.issue_id = tableA.issue_id)
WHERE issue_id IN (SELECT issue_id FROM update_end_date);
Another possibility to #Lukas solution is using proprietary PostgreSQL's syntax UPDATE FROM
UPDATE tablea
SET end_date = max_end_date
FROM update_end_date
WHERE tablea.issue_id = update_end_date.issue_id

PostgreSQL SELECT date before max(DATE)

I need to select the rows for which the difference between max(date) and the date just before max(date) is smaller than 366 days. I know about SELECT MAX(date) FROM table to get the last date from now, but how could I get the date before?
I would need a query of this kind:
SELECT code, MAX(date) - before_date FROM troncon WHERE MAX(date) - before_date < 366 ;
NB : before_date does not refer to anything and is to be replaced by a functionnal stuff.
Edit : Example of the table I'm testing it on:
CREATE TABLE troncon (code INTEGER, ope_date DATE) ;
INSERT INTO troncon (code, ope_date) VALUES
('C086000-T10001', '2014-11-11'),
('C086000-T10001', '2014-11-11'),
('C086000-T10002', '2014-12-03'),
('C086000-T10002', '2014-01-03'),
('C086000-T10003', '2014-08-11'),
('C086000-T10003', '2014-03-03'),
('C086000-T10003', '2012-02-27'),
('C086000-T10004', '2014-08-11'),
('C086000-T10004', '2013-12-30'),
('C086000-T10004', '2013-06-01'),
('C086000-T10004', '2012-07-31'),
('C086000-T10005', '2013-10-01'),
('C086000-T10005', '2012-11-01'),
('C086000-T10006', '2014-04-01'),
('C086000-T10006', '2014-05-15'),
('C086000-T10001', '2014-07-05'),
('C086000-T10003', '2014-03-03');
Many thanks!
The sub query contains all rows joined with the unique max date, and you select only ones which there differente with the max date is smaller than 366 days:
select * from
(
SELECT id, date, max(date) over(partition by code) max_date FROM your_table
) A
where max_date - date < interval '366 day'
PS: As #a_horse_with_no_name said, you can partition by code to get maximum_date for each code.

Postgres: select the sum of values and then sum this again

I tried a lot but can´t find the right way.
If I select values in Postgres and sum them it looks like this:
SELECT name,sum(size) as total
FROM mytable group by name order by name;
How can I alter this so it also sum all values in total? I think I need a subselect but how?
Try this:
SELECT sum(a.total)
FROM (SELECT sum(size) as total
FROM mytable group by name) a
UPDATE
I'm sorry, I don't read that you want it all in the same query. For this reason the answer of greg it's better. However, other possibility if you have a postgresql version >= 9:
WITH mytableWith (name, sum) as
(SELECT name, sum(size)
FROM mytable
GROUP BY name)
SELECT 'grand total' AS name,
sum(sum) AS sum
FROM mytableWith
UNION ALL
SELECT name, sum
FROM mytableWith
I would use the ROLLUP function on POSTRGESQL:
SELECT name,sum(size) as total
FROM mytable
group by ROLLUP(name )
order by name;
This will give you a grand total of any value that you aggregate and can also be used for aggregating multiple columns.
Hope it helps!
If you want all results with the same SELECT, you could do something like
SELECT
'grand total' AS name,
sum(size) AS sum
FROM
mytable
UNION ALL
SELECT
name,
sum(size) AS sum
FROM
mytable
GROUP BY
name;
Hope it helps…
Well this should help you:
select sum(innerselect.innertotal) as outertotal from
(select sum(size) as innertotal from mytable group by name) as innerselect

Two different group by clauses in one query?

First time posting here, a newbie to SQl, and I'm not exactly sure how to word this but I'll try my best.
I have a query:
select report_month, employee_id, split_bonus,sum(salary) FROM empsal
where report_month IN('2010-12-01','2010-11-01','2010-07-01','2010-04-01','2010-09-01','2010-10-01','2010-08-01')
AND employee_id IN('100','101','102','103','104','105','106','107')
group by report_month, employee_id, split_bonus;
Now, to the result of this query, I want to add a new column split_bonus_cumulative that is essentially equivalent to adding a sum(split_bonus) in the select clause but for this case, the group buy should only have report_month and employee_id.
Can anyone show me how to do this with a single query? Thanks in advance.
Try:
SELECT
report_month,
employee_id,
SUM(split_bonus),
SUM(salary)
FROM
empsal
WHERE
report_month IN('2010-12-01','2010-11-01','2010-07-01','2010-04-01','2010-09-01','2010-10-01','2010-08-01')
AND
employee_id IN('100','101','102','103','104','105','106','107')
GROUP BY
report_month,
employee_id;
Assuming you're using Postgres, you might also find window functions useful:
http://www.postgresql.org/docs/9.0/static/tutorial-window.html
Unless I'm mistaking, you want something that resembles the following:
select report_month, employee_id, salary, split_bonus,
sum(salary) over w as sum_salary,
sum(split_bonus) over w as sum_bonus
from empsal
where ...
window w as (partition by employee_id);
CTEs are also convenient:
http://www.postgresql.org/docs/9.0/static/queries-with.html
WITH
rows as (
SELECT foo.*
FROM foo
WHERE ...
),
report1 as (
SELECT aggregates
FROM rows
WHERE ...
),
report2 as (
SELECT aggregates
FROM rows
WHERE ...
)
SELECT *
FROM report1, report2, ...