Oracle SQL Select Date Time with Earliest Time - sql

I have a query that returns this
And I would like to to return this, where earliest hour of the same day is chosen
This is my query so far --- MIN(I.CREATIONDATE) does return the date-time format I want, I was hoping that MIN would select the earliest time.
SELECT TO_CHAR(MIN(I.INCIDENTID)) AS "Incident ID",
MIN(I.CREATIONDATE) AS "Creation Date",
TO_CHAR(I.CREATIONDATE,'MM-DD-YYYY') AS "Date",
TRIM(MO.DOMAINUSERNAME) AS "Login ID",
TRIM(M.MESSAGESUBJECT) AS "Email Subject"
FROM MESSAGE M
JOIN INCIDENT I
ON M.MESSAGESOURCE = I.MESSAGESOURCE
AND M.MESSAGEID = I.MESSAGEID
AND M.MESSAGEDATE = I.MESSAGEDATE
JOIN MESSAGEORIGINATOR MO
ON M.MESSAGEORIGINATORID = MO.MESSAGEORIGINATORID
GROUP BY TO_CHAR(I.CREATIONDATE,'MM-DD-YYYY'),
TRIM(MO.DOMAINUSERNAME),
TRIM(M.MESSAGESUBJECT)

Use row_number()
with CTE as
(
select t1.*,
row_number() over (partition by trunc(creation_date) order by creation_date) rn
from Mytable t1
)
select *
from CTE
where rn = 1

Related

Add ROW_NUMBER() function to SQL query

I have the following query:
select
DISTINCT(b.org),
b.env,
b.proxy,
b."type",
b.name,
b.policytype,
b.disabled,
b."report refresh date",
b.rank,
first_value(LOWER(a."value"))
over(partition by
b.org,
b.env,
b.proxy
order by b."report refresh date" desc
rows between unbounded preceding and unbounded following) as "value"
from
(select *, DENSE_RANK() OVER (ORDER BY "report refresh date" DESC) as rank from infosec.apigee_policy_info_for_proxy) b
left join
(select * from api.apigee_product
where attribute = 'tui-api-domain') a
on a.org = b.org
and a.env = b.env
and a.proxy = b.proxy
where b.rank <=60
group by b.org,
b.env,
b.proxy,
b."type",
b.name,
b.policytype,
b.disabled,
b."report refresh date",
b.rank,
a."value"
and need to add a function in the end of the above query that calculates the row number.
For that I have the following query:
ROW_NUMBER() over (order by "report refresh date" ASC) as rowid
I'm having problems on where to put it, in the first query showned.
Can someone help?
Thank you.
I would simplify this query as :
select distinct b.org, b.env, b.proxy, b.type,b.name,
b.policytype, b.disabled, b."report refresh date", b.rank,
first_value(LOWER(a."value"))
over(partition by b.org, b.env, b.proxy order by b."report refresh date" desc
rows between unbounded preceding and unbounded following) as "value",
ROW_NUMBER() over (order by "report refresh date" ASC) as rowid
from (select *, DENSE_RANK() OVER (ORDER BY "report refresh date" DESC) as rank
from infosec.apigee_policy_info_for_proxy
) b left join
api.apigee_product a
on a.org = b.org and
a.env = b.env and
a.proxy = b.proxy and
a.attribute = 'tui-api-domain'
where b.rank <= 60;
Note : DISTINCT is not function so, removed (). Use LEFT JOIN directly instead of subquery.

calculate time difference of consecutive row dates in SQL

Hello I am trying to calculate the time difference of 2 consecutive rows for Date (either in hours or Days), as attached in the image
Highlighted in Yellow is the result I want which is basically the difference of the date in that row and 1 above.
How can we achieve it in the SQL? Attached is my complex code which has the rest of the fields in it
with cte
as
(
select m.voucher_no, CONVERT(VARCHAR(30),CONVERT(datetime, f.action_Date, 109),100) as action_date,f.col1_Value,f.col3_value,f.col4_value,f.comments,f.distr_user,f.wf_status,f.action_code,f.wf_user_id
from attdetailmap m
LEFT JOIN awftaskfin f ON f.oid = m.oid and f.client ='PC'
where f.action_Date !='' and action_date between '$?datef' and '$?datet'
),
.*select *, ROW_NUMBER() OVER(PARTITION BY action_Date,distr_user,wf_Status,wf_user_id order by action_Date,distr_user,wf_Status,wf_user_id ) as row_no_1 from cte
cte2 as
(
select *, ROW_NUMBER() OVER(PARTITION BY voucher_no,action_Date,distr_user,wf_Status,wf_user_id order by voucher_no ) as row_no_1 from cte
)
select distinct(v.dim_value) as resid,c.voucher_no,CONVERT(datetime, c.action_Date, 109) as action_Date,c.col4_value,c.comments,c.distr_user,v.description,c.wf_status,c.action_code, c.wf_user_id,v1.description as name,r.rel_value as pay_office,r1.rel_value as site
from cte2 c
LEFT OUTER JOIN aagviuserdetail v ON v.user_id = c.distr_user
LEFT OUTER JOIN aagviuserdetail v1 ON v1.user_id = c.wf_user_id
LEFT OUTER JOIN ahsrelvalue r ON r.resource_id = v.dim_Value and r.rel_Attr_id = 'P1' and r.period_to = '209912'
LEFT OUTER JOIN ahsrelvalue r1 ON r1.resource_id = v.dim_Value and r1.rel_Attr_id = 'Z1' and r1.period_to = '209912'
where c.row_no_1 = '1' and r.rel_value like '$?site1' and voucher_no like '$?trans'
order by voucher_no,action_Date
The key idea is lag(). However, date/time functions vary among databases. So, the idea is:
select t.*,
(date - lag(date) over (partition by transaction_no order by date)) as diff
from t;
I should note that this exact syntax might not work in your database -- because - may not even be defined on date/time values. However, lag() is a standard function and should be available.
For instance, in SQL Server, this would look like:
select t.*,
datediff(second, lag(date) over (partition by transaction_no order by date), date) / (24.0 * 60 * 60) as diff_days
from t;

How to calculate running sums with append-only rows

I have a table where rows are never mutated but only inserted; they are immutable records. It has the following fields:
id: int
user_id: int
created: datetime
is_cool: boolean
likes_fruits: boolean
An object is tied to a user, and the "current" object for a given user is the one that has the latest created date. E.g. if I want to update is_cool for a user, I'd append a record with a new created timestamp and is_cool=true.
I want to calculate how many users are is_cool at the end of each day. I.e. I'd like the output table to have the columns:
day: some kind of date_trunc('day', created)
cool_users_count: number of users that have is_cool at the end of this day.
What SQL query can i write that does this? FWIW I'm using Presto (or Redshift if need to).
Note that there are other columns, e.g. likes_fruits, which means a record where is_cool is false does not mean is_cool was just changed to false - it could have been false for a while.
This is what procedural pseudo-code would look like to represent what I'd want to do in SQL:
// rows = ...
min_date = min([row.created for row in rows])
max_date = max([row.created for row in rows])
counts_by_day = {}
for date in range(min_date, max_date):
rows_up_until_date = [row for row in rows if row.created <= date]
latest_row_by_user = rows_up_until_date.reduce(
{},
(acc, row) => acc[row.user_id] = row,
)
counts_by_day[date] = latest_row_by_user.filter(row => row.is_cool).length
You can do this using jus a query .. try using a sum on boolend and group by
select date(created), sum(is_cool)
from my_table
group by date(created)
or if you need the number of users
select t.date_created, count(*) num_user
from (
select distinct date(created) date_created, user_id
from my_table
where is_cool = TRUE
) t
group by t.date_created
or if need the last value for is_cool
select date(max_date), sum(is_cool)
from (
select t.user_id, t.max_date, m.is_cool, m.user_id
from my_table m
inner join (
select max(date_created) max_date, user_id
from my_table
group by user_id, date(date_created)
) t on t.max_date = m.date_created
and t.user_id = m.user_id
where m.is_cool = TRUE
) t2
group by date(max_date)
A correlated subquery might be the simplest solution. The following gets the value of is_cool for each user on each date:
select u.user_id, d.date,
(select t.is_cool
from t
where t.user_id = u.user_id and
t.created < dateadd(day, 1, d.date)
order by t.created desc
limit 1
) as is_cool
from (select distinct date(created) as date
from t
) d cross join
(select distinct user_id
from t
) u ;
Then aggregate:
select date, sum(is_cool)
from (select u.user_id, d.date,
(select t.is_cool
from t
where t.user_id = u.user_id and
t.created < dateadd(day, 1, d.date)
order by t.created desc
limit 1
) as is_cool
from (select distinct date(created) as date
from t
) d cross join
(select distinct user_id
from t
) u
) ud
group by date;

How do i find the most frequent facility in SQL

Currently, my table comprises two - Facility table Facility table and Booking table Booking table
How do I list the most used popular facility used by the members in 2017?
Year has to be 2017
The most frequent facility used each month
After trying to do
This is what I have now
SELECT
MONTH(b.BookingStartDateTime) AS 'Month',
f.FacilityDesc AS 'MOST FREQUENT'
FROM
Booking b
INNER JOIN
Facility f ON b.FacilityID = f.FacilityID
WHERE
YEAR(b.BookingStartDateTime) = 2017
GROUP BY
MONTH(b.BookingStartDateTime), f.FacilityDesc
ORDER BY
MONTH(b.BookingStartDateTime) DESC
I believe this should work.
select Month, 'Most Frequent' from (
select *, row_number() over (partition by Month order by Frequency desc) rnk from (
SELECT
MONTH(b.BookingStartDateTime) AS 'Month',
f.FacilityDesc AS 'MOST FREQUENT',
count(*) as 'Frequency'
FROM
Booking b
INNER JOIN
Facility f ON b.FacilityID = f.FacilityID
WHERE
YEAR(b.BookingStartDateTime) = 2017
GROUP BY
MONTH(b.BookingStartDateTime), f.FacilityDesc
) rnk
) a where rnk = 1
order by month desc
Added a non-window function version, you need to do inner joins or where exists method to get your result
with rnk as (
SELECT
MONTH(b.BookingStartDateTime) AS 'Month',
f.FacilityDesc AS 'MOST FREQUENT',
count(*) as 'Frequency'
FROM
Booking b
INNER JOIN
Facility f ON b.FacilityID = f.FacilityID
WHERE
YEAR(b.BookingStartDateTime) = 2017
GROUP BY
MONTH(b.BookingStartDateTime), f.FacilityDesc
)
select Month, 'Most Frequent' from rnk where exists(
select Month, freq from (
select Month, max(Frequency) freq from rnk group by Month
) a where a.Month = rnk.Month and a.freq = rnk.Frequency
)
order by Month desc

Return first result only for each unique result

I am having some trouble with duplicating results in SQL Server 2005. I have previously used the ROW NUMBER function to display my query results, but I cannot get the query below to only display rownum 1:
SELECT *
FROM (SELECT l.insbilleddate, l.pickupdate, l.patientname, l.inscompanyname AS Payor, l.tripid,
l.sales, l.cost, l.sales-l.cost AS Profit, l.profitpct AS 'Profit Pct', u.pUPFName + ' ' +
u.pUPLName AS Dispatcher, ROW_NUMBER() OVER (PARTITION BY l.tripid ORDER BY d.trDispatchDate
ASC) AS rownum
FROM pUsersPrinters u
INNER JOIN TranslationDispatch d
INNER JOIN v_OLAPdataTR l ON d.trTripid = l.tripid ON u.pUP_id = d.trDispatchedBy
GROUP BY l.insbilleddate, l.pickupdate, l.patientname, l.inscompanyname, l.tripid, l.sales,
l.cost, l.profitpct, u.pUPFName, u.pUPLName, d.trDispatchDate
HAVING l.insbilleddate >= '6/1/2014' And l.insbilleddate < '7/1/2014' AND l.cost > '0' AND
l.profitpct < '30') q1
WHERE rownum = 1
ORDER BY q1.profitpct
The TranslationDispatch table adds a line each time a user dispatches a trip. If a trip needs to be reassigned the database does not overwrite the original dispatcher, instead it adds another line with the userID, tripID, and dispatch date. The d.trTripid = l.tripid comparison causes the trip to show for each dispatcher that marks it.
As an example, results show as:
TripID trDispatchedBy trDispatchDate
1234 Carlos 6/25/2014 10:00
1234 Tim 6/25/2014 10:02
...but I only want to display Carlos, as he dispatched the trip first.
EDIT: I've adjusted the query above with the help of #Vulcronos to make it work, by adding a table alias (q1) and making the rownum = '1' into rownum = 1 to correctly display my final result.
I would try:
ROW_NUMBER () OVER ( PARTITION BY l.insbilleddate, l.pickupdate, l.patientname,
l.inscompanyname, l.tripid, l.sales, l.cost, l.profitpct, u.pUPFName, u.pUPLName,
d.trDispatchDate ORDER BY trDispatchDate ASC)
This should give you a row number of one on every groups earliest dispatch date. Then you can wrap your whole query in:
select *
from (my_query)
where rownum = 1
How about adding "TOP 1" to the outside query
SELECT TOP 1 *
FROM(SELECT L.Insbilleddate,
L.Pickupdate,
L.Patientname,
L.Inscompanyname AS Payor,
L.Tripid,
L.Sales,
L.Cost,
L.Sales - L.Cost AS Profit,
L.Profitpct AS 'Profit Pct',
U.Pupfname + ' ' + U.Puplname AS Dispatcher,
ROW_NUMBER()OVER(PARTITION BY L.Tripid ORDER BY D.Trdispatchdate ASC)AS Rownum
FROM Pusersprinters U
INNER JOIN Translationdispatch D
INNER JOIN V_Olapdatatr L ON D.Trtripid = L.Tripid ON U.Pup_Id = D.Trdispatchedby
GROUP BY L.Insbilleddate,
L.Pickupdate,
L.Patientname,
L.Inscompanyname,
L.Tripid,
L.Sales,
L.Cost,
L.Profitpct,
U.Pupfname,
U.Puplname,
D.Trdispatchdate
HAVING L.Insbilleddate >= '6/1/2014'
AND L.Insbilleddate < '7/1/2014'
AND L.Cost > '0'
AND L.Profitpct < '30') A
ORDER BY A.Profitpct;