How to calculate the days between 2 dates from 2 successive IDs - sql-server

I need some help to create a new column in a database in SQL Server 2008.
I have the following data table
Please have a look at a snapshot of my table
Table
In the blank column I would like to put the difference between the current status date and the next status' date. And for the last ID_Status for each ID_Ticket I would like to have the difference between now date and it's date !
I hope that you got an idea about my problem.
Please share if you have any ideas about how to do .
Many thanks
kind regards

You didn't specify your RDBMS, so I'll post an answer for both since they are almost identical :
SQL-Server :
SELECT ss.id_ticket,ss.id_status,ss.date_status,
DATEDIFF(day,ss.date_status,ss.coalesce(ss.next_date,GETDATE())) as diffStatus
FROM (
SELECT t.*,
(SELECT TOP 1 s.date_status FROM YourTable s
WHERE t.id_ticket = s.id_ticket and s.date_status > t.date_status
ORDER BY s.date_status ASC) as next_date)
FROM YourTable t) ss
MySQL :
SELECT ss.id_ticket,ss.id_status,ss.date_status,
DATEDIFF(ss.date_status,ss.coalesce(ss.next_date,now())) as diffStatus
FROM (
SELECT t.*,
(SELECT s.date_status FROM YourTable s
WHERE t.id_ticket = s.id_ticket and s.date_status > t.date_status
ORDER BY s.date_status ASC limit 1) as next_date)
FROM YourTable t) ss
This basically first use a correlated sub query to bring the next date using limit/top , and then wrap it with another select to calculate the difference between them using DATEDIFF().
Basically it can be done without the wrapping query, but it won't be readable since the correlated query will be inside the DATEDIFF() function, so I prefer this way.

Related

Find customer who placed order every month and who did not place order every month

I am looking for a query than can list the customers
who placed order every month form the following table? A: 123
who did not place an order every month? A:everyone except 123
I am not proficient in such codes and I tried build sub-queries and cte's but I am not able to build my logic. I tried the following but not able to progress.
; with cte as(
SELECT customer_id,DATEPART(MONTH,Customer) as month,count(units) as no_of_order
from dwqc.dbo.orders
group by customer_id,DATEPART(MONTH,Customer))
select * from cte
Could someone please help me out with this? Thanks!
SELECT customer_id
from dwqc.dbo.orders
group by customer_id
having count(distinct DATEPART(MONTH,Customer))
= (select count(distinct DATEPART(MONTH,Customer)) from dwqc.dbo.orders)
Thanks #Nick.McDermaid

Datediff last and previous dates SQL

I'm learning SQL, for an exercise I have to several things.
I'm making a query to compare the most recent orderdate with the orderdate before. I want to use a correlated subquery for this. I have already made it using a Cross Apply and Window functions.
At the moment I have this:
select
b1.klantnr,
DATEDIFF(D, (Select MAX(b1.Besteldatum)),
(Select MAX(b1.Besteldatum)
where besteldatum not in (Select MAX(b1.besteldatum)))) as verschil
from
bestelling b1
group by
b1.klantnr, b1.besteldatum
I only get null values in the datediff column. It should return this:
Results
I'm using SQL Server 2014 Management Studio.
Any help appreciated.
Here is one simple way:
select datediff(day, min(bs.Besteldatum), max(bs.Besteldatum)) as most_recent_diff
from (select top (2) bs.*
from bestelling bs
order by bs.Besteldatum
) bs;
This uses a subquery, but not a correlated subquery. Should have really good performance, if you have an index on bestselling(Besteldatum).
A correlated subquery way.
select top 1 bs.*,datediff(day,
(select max(bs1.Besteldatum)
from bestelling bs1
where bs1.Besteldatum<bs.Besteldatum),
bs.Besteldatum
) as diff
from bestelling bs
order by bs.Besteldatum desc
This gives only the difference between latest date and the date preceding it. If you need all records remove top 1 from the query.

T-SQL: GROUP BY, but while keeping a non-grouped column (or re-joining it)?

I'm on SQL Server 2008, and having trouble querying an audit table the way I want to.
The table shows every time a new ID comes in, as well as every time an IDs Type changes
Record # ID Type Date
1 ae08k M 2017-01-02:12:03
2 liei0 A 2017-01-02:12:04
3 ae08k C 2017-01-02:13:05
4 we808 A 2017-01-03:20:05
I'd kinda like to produce a snapshot of the status for each ID, at a certain date. My thought was something like this:
SELECT
ID
,max(date) AS Max
FROM
Table
WHERE
Date < 'whatever-my-cutoff-date-is-here'
GROUP BY
ID
But that loses the Type column. If I add in the type column to my GROUP BY, then I'd get get duplicate rows per ID naturally, for all the types it had before the date.
So I was thinking of running a second version of the table (via a common table expression), and left joining that in to get the Type.
On my query above, all I have to join to are the ID & Date. Somehow if the dates are too close together, I end up with duplicate results (like say above, ae08k would show up once for each Type). That or I'm just super confused.
Basically all I ever do in SQL are left joins, group bys, and common table expressions (to then left join). What am I missing that I'd need in this situation...?
Use row_number()
select *
from ( select *
, row_number() over (partition by id order by date desc) as rn
from table
WHERE Date < 'whatever-my-cutoff-date-is-here'
) tt
where tt.rn = 1
I'd kinda like know how many IDs are of each type, at a certain date.
Well, for that you use COUNT and GROUP BY on Type:
SELECT Type, COUNT(ID)
FROM Table
WHERE Date < 'whatever-your-cutoff-date-is-here'
GROUP BY Type
Basing on your comment under Zohar Peled answer you probably looking for something like this:
; with cte as (select distinct ID from Table where Date < '$param')
select [data].*, [data2].[count]
from cte
cross apply
( select top 1 *
from Table
where Table.ID = cte.ID
and Table.Date < '$param'
order by Table.Date desc
) as [data]
cross apply
( select count(1) as [count]
from Table
where Table.ID = cte.ID
and Table.Date < '$param'
) as [data2]

SQL Server : to get Max date value

I have the following data in the table:
I have tried using the below query to get the latest CMBR_MBST with its respective CMBR_CCMP
SELECT CMBR_CCMP, MAX(CMBR_MBST) AS CMBR_MBST
FROM CMBR
GROUP BY CMBR_CCMP
The result is close to what I need. I just need the extra 2 columns, CMBR_MMBR & CMBR_MBED to be displayed.
For example:
Can someone please help me with the query? Your help would be very much appreciated. Thanks
Here is one way using ROW_NUMBER
SELECT TOP 1 with ties *
FROM CMBR
Order by row_number()over(parition by CMBR_CCMP order by CMBR_MBST desc)
Another way (commonly used technique)
select * from
(
SELECT *,row_number()over(parition by CMBR_CCMP order by CMBR_MBST desc) Rn
FROM CMBR
) A
Where Rn =1

Replace Group By clause with any other clause

In below query, I am using GROUP BY clause to get list of recently updated records depends on updated date. But I would like to have the query without a GROUP BY clause because of some internal reasons. Can please any one help me to solve this.
SELECT Proj_UpdatedDate,
Proj_UpdatedBy
FROM ProjectProgress PP
WHERE Proj_UpdatedDate IN (SELECT MAX(Proj_UpdatedDate)
FROM ProjectProgress
GROUP BY
Proj_ProjectID)
ORDER BY
Proj_ProjectID
Using TOP 1 should give you the same result assuming you meant the MAX(Proj_UpdatedDate):
SELECT Proj_UpdatedDate,
Proj_UpdatedBy
FROM ProjectProgress PP
WHERE Proj_UpdatedDate IN (SELECT TOP 1 Proj_UpdatedDate
FROM ProjectProgress
ORDER BY Proj_UpdatedDate DESC)
ORDER BY
Proj_ProjectID
However your query actually returns multiple dates since it's GROUPED BY Proj_ProjectId (the max date for each project). Is that your desired outcome - to show a list of dates that the projects were updated and by whom?
If so, try using ROW_NUMBER():
SELECT Proj_UpdatedDate, Proj_UpdatedBy
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY Proj_ProjectID ORDER BY Proj_UpdatedBy DESC) rn,
Proj_UpdatedDate,
Proj_UpdatedBy
FROM ProjectProgress
) t
WHERE rn = 1
And here is the SQL Fiddle. This assumes you are running SQL Server 2005 or greater.
Good luck.

Resources