I have same data structure as Select only last value of date?
, but i need to get values for each date, I marked them. The solution for Feroc's question is giving last date only.
localName Date_Time RH
BAG012 2014-10-09 17:17:58.000 16 <--
BAG012 2014-10-09 17:13:28.000 16
BAG012 2014-10-09 17:12:23.000 16
BAG012 2014-10-09 16:52:54.000 16
BAG012 2014-10-08 05:14:56.000 16 <--
BAG012 2014-10-08 04:45:31.000 16
BAG012 2014-10-08 04:44:08.000 16
SAG165 2014-10-28 11:22:14.000 698 <--
SAG165 2014-10-28 11:09:14.000 698
SAG165 2014-10-28 10:53:18.000 698
SAG165 2014-10-27 19:30:14.000 693 <--
SAG165 2014-10-27 19:14:51.000 693
SAG165 2014-10-27 19:13:56.000 693
Here is a code I am using:
WITH CTE AS
(
SELECT LTRIM(localName) as localName, CAST(year(Date_Time) as varchar)+'-'+CAST(month(Date_Time) as varchar)+'-'+CAST(day(Date_Time) as varchar) as date_time, RH, tank, mode,
RN = ROW_NUMBER() OVER (PARTITION BY localName ORDER BY Date_Time DESC)
FROM dbo.SMCData
)
SELECT DISTINCT Date_Time, localName, RH, tank, mode
FROM CTE
WHERE RN = 1
order by LocalName asc
as the datetime includes time also, I tried to remove time and leave only date.
Tried to used DISTINCT Date_Time
both above cases are not making any changes in result.
ANSWER:
thanks for all, the following worked for me:
WITH CTE AS
(
SELECT localName, Date_Time, RH,
RN = ROW_NUMBER() OVER (PARTITION BY localName, CAST(Date_Time AS date) ORDER BY Date_Time DESC)
FROM dbo.TableName
)
SELECT localName, Date_Time, RH
FROM CTE
WHERE RN = 1
ORDER BY localName, Date_Time;
WITH CTE AS
(
SELECT localName, Date_Time, RH,
RN = ROW_NUMBER() OVER (PARTITION BY localName, CAST(Date_Time AS date) ORDER BY Date_Time DESC)
FROM dbo.TableName
)
SELECT localName, Date_Time, RH
FROM CTE
WHERE RN = 1
ORDER BY localName, Date_Time;
Use select distinct:
SELECT DISTINCT date
FROM table_name
It will give you on of each date
Group by the date also:
SELECT localName, MAX(date_time) AS max_date_time, MAX(rh) AS max_rh
FROM your_table
GROUP BY localName, CAST(date_time AS date)
This will give you the last date for each localname.
Sample SQL Fiddle
Output:
localName max_date_time max_rh
---------- ----------------------- -----------
BAG012 2014-10-08 05:14:56.000 16
BAG012 2014-10-09 17:17:58.000 16
SAG165 2014-10-27 19:30:14.000 693
SAG165 2014-10-28 11:22:14.000 698
SELECT DISTINCT localName, Date , RH
FROM table_name
This should give unique date and RH values and corresponding localName.
Related
select timezone('utc'::text,t.assigned_at)::DATE as time,
organization_id as org_id,
row_number () over (partition by organization_id order by t.assigned_at desc ) as rownumber
from table t
> time org_id rownumber
> 06.01.2021 13 5
> 06.01.2021 13 4
> 06.01.2021 13 3
> 06.01.2021 13 2
> 06.01.2021 13 1
> 06.01.2021 34 3
> 06.01.2021 34 2
> 06.01.2021 34 1
I need 34: 1, 2, 3.
How to put a search term in a subquery?
select *
from (
select timezone('utc'::text,t.assigned_at)::DATE as time,
organization_id as org_id,
row_number () over (partition by organization_id order by t.assigned_at desc ) as rownumber
from table t
) z
where z.rownumber = ?????
I need 34: 1, 2, 3. How to put a search term in a subquery?
Just put a WHERE clause into the subquery:
select *
from (
select timezone('utc'::text,t.assigned_at)::DATE as time
, organization_id as org_id
, row_number ()
over (partition by organization_id order by t.assigned_at desc )
as rownumber
from table t
WHERE t.organization_id = 34
) z
where z.rownumber < 4
;
dense_rank () over (partition by timezone('utc'::text, t.assigned_at)::date,order by ds.organization_id desc) as dec
where dec=1
I'm trying to display an accounting report where I show total transactions, voids, the transaction fee, and a total amount for each transaction type.
TransactionType Amount TransactionCount TotalAmount
AgentCredit -$1.00 49 -$49.00
MailFee -$1.25 11 -$13.75
MailFee $1.25 531 $663.75
HardCardFee -$5.00 7 -$35.00
HardCardFee $5.00 239 $1,195.00
QuotaHuntFee -$2.00 1 -$2.00
QuotaHuntFee $2.00 202 $404.00
But what I want to display would look like the following:
TransactionType Amount TransactionCount TotalAmount TotalTrans Voids
AgentCredit -$1.00 49 -$49.00 49 0
MailFee $1.25 520 $650.00 531 11
HardCardFee $5.00 232 $1,160.00 239 7
QuotaHuntFee $2.00 201 $402.00 202 1
Would it be possible to group the transaction types using the absolute value of the Amount and calculate the grand total along with the transaction count & void counts?
This is on SQL Server 2014.
Thanks,
I think this does it
declare #T table (nm varchar(20), prc smallmoney, amt int);
insert into #T values
('AgentCredit', -1.00, 49)
, ('MailFee', -1.25, 11)
, ('MailFee', 1.25, 531)
, ('HardCardFee', -5.00, 7)
, ('HardCardFee', 5.00, 239)
, ('QuotaHuntFee', -2.00, 1)
, ('QuotaHuntFee', 2.00, 202);
with cte as
(
select t.*, (t.prc * t.amt) as net
, count(*) over (partition by t.nm, abs(t.prc)) as cnt
, row_number() over (partition by t.nm, abs(t.prc) order by t.prc) as rn
, lag(t.prc) over (partition by t.nm, abs(t.prc) order by t.prc) as prPrc
, lag(t.amt) over (partition by t.nm, abs(t.prc) order by t.prc) as prAmt
, case when lag(t.prc) over (partition by t.nm, abs(t.prc) order by t.prc) < 0 then t.amt - lag(t.amt) over (partition by t.nm, abs(t.prc) order by t.prc)
else t.amt
end as bal
from #T t
)
select *, ISNULL(t.prAmt, 0) as void
, bal*prc as nnet
from cte t
where t.cnt = 1
or t.rn = 2
order by t.nm, t.prc;
There's a bit of confusion around your results with the data you've provided. HardCardFee has 7 and 23 in the sample you provided, but you want to return 232 for the total?.. MailFee also has some inconsistent math. Also, your 'Voids' returns 0 for the first row; however, it seems as if there are 49?
Perhaps this query could get you started down the right path:
DECLARE #Table TABLE (TransactionType varchar(20), Amount decimal(10,2), TransactionCount int, TotalAmount decimal(10,2))
INSERT #Table
VALUES ('AgentCredit' ,-$1.00 ,49 ,-$49.00 ),
('MailFee' ,-$1.25 ,11 ,-$13.75 ),
('MailFee' ,$1.25 ,531 ,$663.75 ),
('HardCardFee' ,-$5.00 ,7 ,-$35.00 ),
('HardCardFee' ,$5.00 ,23 ,$1195.00 ),
('QuotaHuntFee' ,-$2.00 ,1 ,-$2.00 ),
('QuotaHuntFee' ,$2.00 ,202 ,$404.00 )
;WITH c AS (
SELECT TransactionType, Amount, TransactionCount, TotalAmount,
CASE WHEN t.Amount + ABS(t.Amount) = 0 THEN '-' ELSE '' END +
CAST(t.TransactionCount AS VARCHAR(10)) AS TCount
FROM #Table t
)
SELECT t.TransactionType
,MAX(t.Amount) AS Amount
,SUM(CAST(t.TCount AS INT)) AS TransactionCount
,SUM(t.TotalAmount) AS TotalAmount
,SUM(ABS(t.TransactionCount)) AS TotalTrans
,ABS(MIN(t.TCount)) AS Voids
FROM c t
GROUP BY TransactionType
Again, not sure about some of the values provided.
I have this datset:
create table #date_example
(
date_val datetime, rownum int
)
insert #date_example values('3/1/14',1)
insert #date_example values('3/1/14',2)
insert #date_example values('3/1/14',3)
insert #date_example values('2/1/14',4)
insert #date_example values('1/3/14',5)
select --top 1 with ties
date_val,
ROW_NUMBER() OVER(PARTITION BY rownum ORDER BY date_val DESC) AS 'RowNum'
from #date_example
order by date_val
desc
With output:
date_val RowNum
2014-03-01 00:00:00.000 1
2014-03-01 00:00:00.000 1
2014-03-01 00:00:00.000 1
2014-02-01 00:00:00.000 1
2014-01-03 00:00:00.000 1
But I want instead output:
date_val RowNum
2014-03-01 00:00:00.000 1
2014-03-01 00:00:00.000 1
2014-03-01 00:00:00.000 1
2014-02-01 00:00:00.000 2
2014-01-03 00:00:00.000 3
So I want the RowNum to be a ranking which includes ties. How can I do this?
I found the answer from another post:
select
date_val,
Rank() OVER(ORDER BY date_val DESC) AS 'RowNum'
from #date_example
Can some one please help me with how to create end date from start date.
Products referred to a company for testing while the product with the company they carry out multiple tests on different dates and record the test date to establish the product condition i.e. (outcomeID).
I need to establish the StartDate which is the testDate and EndDate which is the start date of the next row. But if multiple consecutive tests resulted in the same OutcomeID I need to return only one row with the StartDate of the first test and the end date of the last test. In another word if the outcomeID did not change over a few consecutive tests.
Here is my data set
DECLARE #ProductTests TABLE
(
RequestID int not null,
ProductID int not null,
TestID int not null,
TestDate datetime null,
OutcomeID int
)
insert into #ProductTests
(RequestID ,ProductID ,TestID ,TestDate ,OutcomeID )
select 1,2,22,'2005-01-21',10
union all
select 1,2,42,'2007-03-17',10
union all
select 1,2,45,'2010-12-25',10
union all
select 1,2,325,'2011-01-14',13
union all
select 1,2,895,'2011-08-10',15
union all
select 1,2,111,'2011-12-23',15
union all
select 1,2,636,'2012-05-02',10
union all
select 1,2,554,'2012-11-08',17
--select *from #producttests
RequestID ProductID TestID TestDate OutcomeID
1 2 22 2005-01-21 10
1 2 42 2007-03-17 10
1 2 45 2010-12-25 10
1 2 325 2011-01-14 13
1 2 895 2011-08-10 15
1 2 111 2011-12-23 15
1 2 636 2012-05-02 10
1 2 554 2012-11-08 17
And this is what I need to achieve.
RequestID ProductID StartDate EndDate OutcomeID
1 2 2005-01-21 2011-01-14 10
1 2 2011-01-14 2011-08-10 13
1 2 2011-08-10 2012-05-02 15
1 2 2012-05-02 2012-11-08 10
1 2 2012-11-08 NULL 17
As you see from the dataset the first three tests (22, 42, and 45) all resulted in OutcomeID 10 so in my result I only need start date of test 22 and end date of test 45 which is the start date of test 325.As you see in test 636 outcomeID has gone back to 10 from 15 so it needs to be returned too.
--This is what I have managed to achieve at the moment using the following script
select T1.RequestID,T1.ProductID,T1.TestDate AS StartDate
,MIN(T2.TestDate) AS EndDate ,T1.OutcomeID
from #producttests T1
left join #ProductTests T2 ON T1.RequestID=T2.RequestID
and T1.ProductID=T2.ProductID and T2.TestDate>T1.TestDate
group by T1.RequestID,T1.ProductID ,T1.OutcomeID,T1.TestDate
order by T1.TestDate
Result:
RequestID ProductID StartDate EndDate OutcomeID
1 2 2005-01-21 2007-03-17 10
1 2 2007-03-17 2010-12-25 10
1 2 2010-12-25 2011-01-14 10
1 2 2011-01-14 2011-08-10 13
1 2 2011-08-10 2011-12-23 15
1 2 2011-12-23 2012-05-02 15
1 2 2012-05-02 2012-11-08 10
1 2 2012-11-08 NULL 17
nov 7 but still not answered
so here is my solution
not soo pretty but works
my hint is read about windowing , ranking and aggregate functions like row_number, rank , avg, sum etc.
those are essential when you want to write raports , and becoming quite powerfull in sql server 2012
i have also used CTE (common table expression) but it can be written as subquery or temporary table
;with cte ( ida, requestid, productid, testid, testdate, outcomeid) as
(
-- select rows where the outcome id is changing
select b.* from
(select ROW_NUMBER() over( partition by requestid, productid order by testDate) as id, * from #ProductTests)a
right outer join
(select ROW_NUMBER() over(partition by requestid, productid order by testDate) as id, * from #ProductTests) b
on a.requestID = b.requestID and a.productID = b.productID and a.id +1 = b.id
where 1=1
--or a.id = 1
and a.outcomeid <> b.outcomeid or b.outcomeid is null or a.id is null
)
select --*
a.RequestID,a.ProductID,a.TestDate AS StartDate ,MIN(b.TestDate) AS EndDate ,a.OutcomeID
from cte a left join cte b on a.requestid = b.requestid and a.productid = b.productid and a.testdate < b.testdate
group by a.RequestID,a.ProductID ,a.OutcomeID,a.TestDate
order by StartDate
Actually, there seem to be two problems in your question. One is how to group sequential (based on specific criteria) rows containing the same value. The other is the one actually spelled out in your title, i.e. how to use the next row's StartDate as the current row's EndDate.
Personally, I would solve these two problems in the order I mentioned them, so I would first address the grouping problem. One way to group the data properly in this case would be to use double ranking like this:
WITH partitioned AS (
SELECT
*,
grp = ROW_NUMBER() OVER (PARTITION BY RequestID, ProductID ORDER BY TestDate)
- ROW_NUMBER() OVER (PARTITION BY RequestID, ProductID, OutcomeID ORDER BY TestDate)
FROM #ProductTests
)
, grouped AS (
SELECT
RequestID,
ProductID,
StartDate = MIN(TestDate),
OutcomeID
FROM partitioned
GROUP BY
RequestID,
ProductID,
OutcomeID,
grp
)
SELECT *
FROM grouped
;
This should give you the following output for your data sample:
RequestID ProductID StartDate OutcomeID
--------- --------- ---------- ---------
1 2 2005-01-21 10
1 2 2011-01-14 13
1 2 2011-08-10 15
1 2 2012-05-02 10
1 2 2012-11-08 17
Obviously, one thing is still missing, and it's EndDate, and now is the right time to care about it. Use ROW_NUMBER() once again, to rank the result set of the grouped CTE, then use the rankings in the join condition when joining the result set with itself (using an outer join):
WITH partitioned AS (
SELECT
*,
grp = ROW_NUMBER() OVER (PARTITION BY RequestID, ProductID ORDER BY TestDate)
- ROW_NUMBER() OVER (PARTITION BY RequestID, ProductID, OutcomeID ORDER BY TestDate)
FROM #ProductTests
)
, grouped AS (
SELECT
RequestID,
ProductID,
StartDate = MIN(TestDate),
OutcomeID,
rnk = ROW_NUMBER() OVER (PARTITION BY RequestID, ProductID ORDER BY MIN(TestDate))
FROM partitioned
GROUP BY
RequestID,
ProductID,
OutcomeID,
grp
)
SELECT
g1.RequestID,
g1.ProductID,
g1.StartDate,
g2.StartDate AS EndDate,
g1.OutcomeID
FROM grouped g1
LEFT JOIN grouped g2
ON g1.RequestID = g2.RequestID
AND g1.ProductID = g2.ProductID
AND g1.rnk = g2.rnk - 1
;
You can try this query at SQL Fiddle to verify that it returns the output you are after.
Can you show how can this be done in t-sql?
sample records
accountnumber trandate
-------------------------
1000 02-11-2010
1000 02-12-2010
1000 02-13-2010
2000 02-10-2010
2000 02-15-2010
How to compute the # of days between each transactions for each accountnumber?
like this
accountnumber trandate # of days
----------------------------------------
1000 02-11-2010 0
1000 02-12-2010 1
1000 02-13-2010 1
2000 02-10-2010 0
2000 02-15-2010 5
Thanks a lot!
SELECT accountnumber,
trandate,
Datediff(DAY, a.trandate, (SELECT TOP 1 trandate
FROM mytable b
WHERE b.trandate > a.trandate
ORDER BY trandate))
FROM mytable a
ORDER BY trandate
you can use between and
select * from table1 where trandate between 'date1' and 'date2'
Hope this helps.
Select A.AccountNo, A.TranDate, B.TranDate as PreviousTranDate, A.TranDate - B.Trandate as NoOfDays
from
(Select AccountNo, TranDate, Row_Number() as RNO over (Partition by AccountNo order by TranDate)) as A,
(Select AccountNo, TranDate, Row_Number() as RNO over (Partition by AccountNo order by TranDate)) as B
Where A.AccountNo = B.AccountNo and A.RNO -1 = B.RNO
You can also use a CTE expression to increase preformance.