Group by clause - output is not as expected - sql

Below is my sql query to get the list of dates from a table.
select t2.counter_date as myDates from table1 t1;
output:
myDates
2014-03-14 00:00:00
2014-05-11 00:00:00
2014-11-03 00:00:00
2014-12-23 00:00:00
2015-01-12 00:00:00
2015-08-08 00:00:00
2016-03-14 00:00:00
2017-03-14 00:00:00
2017-03-19 00:00:00
Below is the solution:
select min(t1.counter_date) as oldDate,max(t1.counter_date) as latestDate from table1 t1;

In the following demo you can see that your query is giving the correct results. The problem must be in your data.
EDIT: after the edit it is clear where the problem is. Once you perform the following query:
SELECT min(date), max(date)
FROM tab
GROUP BY date
than min(date) has to be equal to max(date) since there is just one date in the group.

Related

Oracle Recursive Query in a History table

I want to do a recursive query in User History Table. I tried with the below query its giving only one record. Since its a history table there will be multiple records for particular user with Effective date.
WITH superVis(EMPLID,CH_SUPV_ID) AS (
SELECT A.EMPLID,A.CH_SUPV_ID
FROM PSOFTUDB.PS_CH_RPTS_TO_TBL A WHERE A.EMPLID = #Param AND A.EFFDT = (select MAX(A2.EFFDT) from PSOFTUDB.PS_CH_RPTS_TO_TBL A2 WHERE A2.EMPLID = A.EMPLID)
UNION ALL
SELECT e.EMPLID,e.CH_SUPV_ID FROM
PSOFTUDB.PS_CH_RPTS_TO_TBL e,superVis o where
o.CH_SUPV_ID = e.EMPLID
) select * from superVis;
i want hierarchy of user with the respected manager. I was able to acheive this in DB2. When changing it to oracle am getting error.
Latest effective date of the current manager is the data to be used in the query.
Sample Data :
EMPLID CH_SUPV_ID EFFDT
1844854 1730352 2020-12-03 00:00:00
1730352 1461958 2018-12-17 00:00:00
1461958 246001 2014-02-04 00:00:00
1461958 954507 2021-06-10 00:00:00
246001 123345 1999-04-12 00:00:00
246001 17139 1999-08-23 00:00:00
246001 18382 2004-04-13 00:00:00
246001 18442 2007-07-27 00:00:00
954507 971510 2019-05-01 00:00:00
Expected Output:
EMLID CH_SUPV_ID EFFDAT
1844854 1730352 2020-12-03 00:00:00
1730352 1461958 2018-12-17 00:00:00
1461958 954507 2021-06-10 00:00:00
954507 971510 2019-05-01 00:00:00
First, deal with effective dates. This is what I did in the "temp" CTE. It shows max effective date for each emplid.
Having done that, you can easily get what you need using oracle's hierarchical queries feature.
with temp as (
select EMPLID, CH_SUPV_ID, EFFDT, max(effdt) over(partition by emplid) maxdate
from PS_CH_RPTS_TO_TBL
)
select *
from temp
connect by nocycle EMPLID = prior CH_SUPV_ID and effdt = maxdate
start with emplid = 1844854

How can I extract the values of the last aggregation date in sql

I have the following table.
id user time_stamp
1 Mike 2020-02-13 00:00:00 UTC
2 John 2020-02-13 00:00:00 UTC
3 Levy 2020-02-12 00:00:00 UTC
4 Sam 2020-02-12 00:00:00 UTC
5 Frodo 2020-02-11 00:00:00 UTC
Let's say 2020-02-13 00:00:00 UTC is the last day and I would like to query this table to only display last days results? I want to create a view in Bigquery so that I only and always get the last day's results?
So that in the end I get something like this (For last day which is 2020-02-13 00:00:00 UTC )
id user time_stamp
1 Mike 2020-02-13 00:00:00 UTC
2 John 2020-02-13 00:00:00 UTC
You can use window functions:
select t.* except (seqnum)
from (select t.*,
dense_rank() over (order by time_stamp) as seqnum
from t
) t
where seqnum = 1;
This may not work well on a large amount of data -- because of the way that BQ implements window functions with no partitioning. So, you might find that this works better (especially if the above runs out of resources):
select t.*
from t join
(select max(time_stamp) as max_time_stamp
from t
) tt
on t.time_stamp = max_time_stamp;
Also, if the timestamps actually have date components, then you will want to convert to a date or remove the time component somehow.

Select to search column on group by query

I have one table called prices that have a reference from table products through product_id column. I want a query that selects prices grouped by product_id with the max final date and get the value of start_date through one select with id of price grouped.
I try with the following query but I am getting a wrong value of start date. Is weird because of the result subquery return more than one row even though I use the price id on where clause. Because that I put the limit on the query but it is wrong.
select prices.produto_id, prices.id,
MAX(CASE WHEN prices.finish_date IS NULL THEN COALESCE(prices.finish_date,'9999-12-31') ELSE prices.finish_date END) as finish_date,
(select start_date from prices where prices.id = prices.id limit 1)
as start_date from prices group by prices.product_id, prices.id
How I can get the relative start date of the price id in my grouped row? I am using postgresql.
A example to view what I want with my query:
DataSet:
ID | PRODUCT_ID | START_DATE | FINISH_DATE
1 1689 2018-01-19 02:00:00 2019-11-19 23:59:59
2 1689 2019-10-11 03:00:00 2019-10-15 23:59:59
3 1689 2019-01-11 03:00:00 2019-05-15 23:59:59
4 1690 2019-11-11 03:00:00 2019-12-15 23:59:59
5 1690 2019-05-11 03:00:00 2025-12-15 23:59:59
6 1691 2019-05-11 03:00:00 null
I want this result:
ID | PRODUCT_ID | START_DATE | FINISH_DATE
1 1689 2018-01-19 02:00:00 2019-11-19 23:59:59
5 1690 2019-05-11 03:00:00 2025-12-15 23:59:59
6 1691 2019-05-11 03:00:00 9999-12-31 23:59:59
The start date should be the same value of the row before the group by.
I would recommend DISTINCT ON in Postgres:
select distinct on (p.product_id) p.*
from prices p
order by p.product_id,
p.finish_date desc nulls first;
NULL values are treated as larger than any other value, so a descending sort puts them first. However, I've included nulls first just to be explicit.
DISTINCT ON is a very handy Postgres extension, which you can learn more about in the documentation.
Try this
with data as (
SELECT id, product_id,
max(COALESCE(finish_date,'9999-12-31')) as finish_date from prices group by 1,2)
select d.*, p.start_date from data d join prices p on p.id = d.id;
It surely isnt' the most elegant solution, but it should work.

SQL DateDiff - return row when one date field is 2 months older than another date field

Each row has a BookedMonth and a ReportingMonth. I want to return the rows where the ReportingMonth is 2 Months greater than the BookedMonth.
ReportingMonth BookedMonth
2016-01-01 00:00:00 2015-11-01 00:00:00
2016-01-01 00:00:00 2015-12-01 00:00:00
2016-01-01 00:00:00 2016-01-01 00:00:00
WHERE
DATEDIFF,BookedMonth,ReportingMonth,2
Something like:
select * from table where datediff(month, ReportingMonth, BookedMonth) > 2;
EDIT
Or better... se comments here below:
select * from table where ReportingMonth > dateadd(month, 2, BookedMonth);

PostgreSQL query for multiple update

I have a table in which I have 4 columns: emp_no,desig_name,from_date and to_date:
emp_no desig_name from_date to_date
1001 engineer 2004-08-01 00:00:00
1001 sr.engineer 2010-08-01 00:00:00
1001 chief.engineer 2013-08-01 00:00:00
So my question is to update first row to_date column just one day before from_date of second row as well as for the second one aslo?
After update it should look like:
emp_no desig_name from_date to_date
1001 engineer 2004-08-01 00:00:00 2010-07-31 00:00:00
1001 sr.engineer 2010-08-01 00:00:00 2013-07-31 00:00:00
1001 chief.engineer 2013-08-01 00:00:00
You can calculate the "next" date using the lead() function.
This calculated value can then be used to update the table:
with calc as (
select promotion_id,
emp_no,
from_date,
lead(from_date) over (partition by emp_no order by from_date) as next_date
from emp
)
update emp
set to_date = c.next_date - interval '1' day
from calc c
where c.promotion_id = emp.promotion_id;
As you can see getting that value is quite easy, and storing derived information is very often not a good idea. You might want to consider a view that calculates this information on the fly so you don't need to update your table each time you insert a new row.
SQLFiddle example: http://sqlfiddle.com/#!15/31665/1