Get the rows with the latest date for an ID [closed] - sql

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
My table has multiple rows for each id, with a calculated score and the date the calculation was done. Simplifying, it looks like this:
id
calc_score
date
1
82
today
1
53
yesterday
1
92
last week
2
23
today
2
60
yesterday
2
73
last week
I need a query that returns only today's scores for each ID. I tried various combinations of group by and distinct on but didn't get very far.
What's the best way for doing this?

PG has several ways. A simple approach is window functions, row_number, rank, etc.
The following will answer the question in your title, to return the latest (last) row per id (by date), which is different than the body of your question.
WITH cte AS (
SELECT t.*
, row_number() OVER (PARTITION BY id ORDER BY date DESC) AS rn
FROM scores
)
SELECT * FROM cte
WHERE rn = 1
;
This just picks the (latest dated) first row for each id based on the date column descending. This also assumes the date column really contains date values or something orderable like a date.
To answer your question in the question body:
I need a query that returns only today's scores for each ID
more strictly, we could also do this:
SELECT *
FROM scores
WHERE date = current_date
;

If you want only today's scores, then you could use a direct comparison if the date has no time component:
where date = current_date
Or for either dates or timestamps:
where date >= current_date and date < current_date + interval '1 day'
If you want the most recent row per id, you would use distinct on:
select distinct on (id) t.*
from t
order by id, date desc;

Related

SQL query to get time spent on specific statuses based on single datetime column [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I need to build a SQL query in which I can get time spent on multiple statuses (onHold,Waiting for customer,Resolved,Closed), so basically I do not want to include time spent on this statues and table looks like as below
So I need a query in which I can get actual time spent on ticket or time spent on status which I have mentioned so far I have tried below solutions and tried Cross APPLY but seems all did not help me as expected.
Tried below query so far and that gives me correct time spent on first status on-hold not after that:
SELECT t1.TICKETNUMBER,SUM(DATEDIFF(MINUTE,TICKETTIME,CloseTime)) as TotalMinutes
FROM [Admin].[TbtrnTicketHistory] t1
CROSS APPLY(SELECT TOP 1 TICKETTIME as CloseTime FROM [Admin].[TbtrnTicketHistory] t2 WHERE t1.TICKETNUMBER = t2.TICKETNUMBER and t2.TICKETHISTORYID > t1.TICKETHISTORYID ORDER BY t2.TICKETTIME) as t2
WHERE t1.CURRENTSTATUS_ANALYST not in('On-Hold','Waiting For Customer','Resolved','Closed') and t1.ticketnumber = '211135'
GROUP BY t1.TICKETNUMBER;
calculate difference between two times in two rows in sql
Calculate Time Difference Between Two Consecutive Rows
with SQL Server you can use those very usefull windowed functions LEAD and FIRST_VALUE :
select *
,[duration(sec)] = DATEDIFF(SECOND
,ticketTime
,LEAD(ticketTime,1,ticketTime)over(partition by ticketNumber order by ticketTime)
)
,[cumulative duration(sec)] = DATEDIFF( SECOND
, FIRST_VALUE(ticketTime)over(partition by ticketNumber order by ticketTime)
, ticketTime)
from (values
(1,cast('20211101 10:00:01' as datetime))
,(1,'20211101 10:00:33')
,(1,'20211101 10:01:59')
)T(ticketNumber,ticketTime)
ticketNumber
ticketTime
duration(sec)
cumulative duration(sec)
1
2021-11-01 10:00:01.000
32
0
1
2021-11-01 10:00:33.000
86
32
1
2021-11-01 10:01:59.000
0
118

Write a query to display unique student ID who joined in the month of June. Sort the result in ascending order [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
this is what I tried-
select distinct studid
from registration
where to_char(doj,'MM')='june'
order by studid;
but I did not get the desired results.
TO_CHAR() with MM parameter will give you 06, instead of JUNE. You may try below query instead -
select distinct studid
from registration
where to_char(doj,'MM')='06'
order by studid;
Rather than using TO_CHAR, You should use oracle specific function EXTRACT -
select distinct studid
from registration
where extract(month from doj) = 6
order by studid;
I assume that you are running Oracle, as the use of to_char() suggests.
If you want students that joined in june of a given year, say 2019, then I would recommend to check doj against a half-open interval (this is more efficient than applying a date function on the column):
select distinct studid
from registration
where doj >= date '2019-06-01' and doj < date '2019-07-01'
order by studid
On the other hand, if you want sudents that joined in any month of june:
select distinct studid
from registration
where extract(month from doj) = 6
order by studid

sum last n days quantity using sql window function

I am trying to create following logic in Alteryx and data is coming from Exasol database.
Column “Sum_Qty_28_days“ should sum up the values of “Qty ” column for same article which falls under last 28 days.
My sample data looks like:
and I want following output:
E.g. “Sum_Qty_28_days” value for “article” = ‘A’ and date = ‘’2019-10-8” is 8 because it is summing up the “Qty” values associated with dates (coming within previous 28 days) Which are:
2019-09-15
2019-10-05
2019-10-08
for “article” = ‘A’.
Is this possible using SQL window function?
I tried myself with following code:
SUM("Qty") OVER (PARTITION BY "article", date_trunc('month',"Date")
ORDER BY "Date")
But, it is far from what I need. It is summing up the Qty for dates falling in same month. However, I need to sum of Qty for last 28 days.
Thanks in advance.
Yes, this is possible using standard SQL and in many databases. However, this will not work in all databases:
select t.*,
sum(qty) over (partition by article
order by date
range between interval '27 day' preceding and current row
) as sum_qty_28_days
from t;
If your RDBMS does not support the range frame, an alternative solution is to use an inline subquery:
select
t.*,
(
select sum(t1.qty)
from mytable t1
where
t1.article = t.article
and t1.date between t.date - interval 28 days and t.date
) sum_qty_28_days
from mytable t

Date minus date query [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have a query like below and I want to make calculation for end_scan-packing_date column, how can I achieve this?
SELECT a.invoice_no,
CONVERT(VARCHAR, b.packing_date,3) as packing_date ,
CONVERT(VARCHAR, b.exw_date,3) as exw,
CONVERT(VARCHAR, b.bcd_end_date, 3) as end_date,
(SELECT TOP 1 insert_date FROM wms.bcd_shipment d,wms.shinvoicedetails WHERE d.invoice_no = a.invoice_no ORDER BY insert_date ASC) as start_date ,
(SELECT TOP 1 insert_date FROM wms.bcd_shipment d,wms.shinvoicedetails WHERE d.invoice_no = a.invoice_no ORDER BY insert_date DESC) as end_scan,
CONVERT(VARCHAR, send_date, 3) as swnd_date,customer_short_name,
Sum(picking_qty) as qty,total_carton
FROM wms.shinvoicedetails a,
wms.shinvoiceheder b,
wms.shinvoice_ctrl c
WHERE send_date BETWEEN '2014/8/26 00:00:01' AND '2014/9/25 23:59:59'
AND a.invoice_no = b.invoice_no
AND a.invoice_no = c.invoice_no
GROUP BY a.invoice_no,
b.packing_date,
b.exw_date,
b.bcd_end_date,
send_date,
customer_short_name,
total_carton
ORDER BY 1;
May I refer you to the documentation for the DATEDIFF function (I'm assuming your're using SQL Server as RDBMS).
It has 3 parameters, I am assuming you want the difference in days. So what you want would read something like:
DATEDIFF(DAY,
(SELECT TOP 1 insert_date
FROM wms.bcd_shipment d,
wms.shinvoicedetails
WHERE d.invoice_no = a.invoice_no
ORDER BY insert_date DESC),
b.packing_date
) AS diff_days
Your query is wrong on many levels though. You are grouping on nearly all columns to get a SUM while you should write that as a derived table (a sub-query) grouping only on the necessary fields. Also you are converting to VARCHAR which probably translates to VARCHAR(1). You should probably write it as CONVERT(VARCHAR(10), <your date field>, 3).
A day does not start at 00:00:01 and does not finish as 23:59:59. Do yourself a favour an don't try to bend your needs to the syntax of between. There is an easier and more reliable method
WHERE send_date >= '20140826' AND send_date < '20140926'
LESS THAN the 26th; it's more accurate & no silly one second deductions.
the best practice with date and time ranges is to avoid BETWEEN and to
always use the form:
WHERE col >= '20120101' AND col < '20120201'
This form works with all
types and all precisions, regardless of whether the time part is
applicable.
Itzik Ben-Gan
http://sqlmag.com/t-sql/t-sql-best-practices-part-2

Selecting products that haven't been made in 2 years

I'm trying to get the products that havn't been made in the last 2 years. I'm not that great with SQL but here's what i've started with and it doesn't work.
Lets say for this example that my schema looks like this
prod_id, date_created, num_units_created.
I'll take any advice i can get.
select id, (select date from table
where date <= sysdate - 740) older,
(select date from table
where date >= sysdate - 740) newer
from table
where newer - older
I'm not being clear enough.
Basically i want all products that havn't been produced in the last 2 years. Whenever a product is produced, a line gets added. So if i just did sysdate <= 740, it would only give me all the products that were produced from the beginning up til 2 years ago.
I want all products that have been produced in the at least once, but not in the last 2 years.
I hope that clears it up.
GROUP BY with HAVING
select id, max(date)
from table
group by id
having max(date) < add_months(sysdate,-24)
I'd use SQL's dateadd function.
where date < dateadd(year,-2,getdate())
would be a where clause that would select records with date less than 2 years from the current date.
Hope that helps.
EDIT: If you want to go by days, use dateadd(d,-740,getdate())
Maybe something like this?
select id, date
from table
where date <= (sysdate - 730);
SELECT id FROM table WHERE date + (365*2) <= sysdate;
Use SELECT id, date, other, columns ... if you need to get them at the same time.