Sum Column as an Accumulation Based on a Time Period - sql-server

I have a table in which records are inserted at different periods (each record contains a column called 'Amount').
I want to show the total amount acummulation, after each 5 seconds. I have tried with the following query without success:
SELECT Sum(totalamount) AS RealTimeTotalAmount,
Datepart(second, createstamp) / 5 AS dp
FROM [order]
WHERE
createstamp BETWEEN Dateadd(s, -5, Getdate()) AND Getdate()
GROUP BY Datepart(second, createstamp) / 5
The problem I am facing is, that it shows me the 'accumulative sum as per each second' and I want to see it like '(accumulative sum as per each second + total accumulative amount till that second)'
Here is how the source data looks like:
-----------------------------------------------------------
|OrderID | CreateStamp | TotalAmount |
-----------------------------------------------------------
|1 |2015-03-22 15:26:05.620 | 10 |
-----------------------------------------------------------
|2 |2015-03-22 15:26:05.653 | 20 |
-----------------------------------------------------------
|3 |2015-03-22 15:26:05.660 | 10 |
-----------------------------------------------------------
|4 |2015-03-22 15:26:06.663 | 10 |
-----------------------------------------------------------
|5 |2015-03-22 15:26:06.670 | 30 |
-----------------------------------------------------------
Essentially, I want the resulting query to return as follows:
----------------------------------------
|Period | Accumulative Amount |
----------------------------------------
|0 to 5 seconds | 30 |
----------------------------------------
|0 to 10 seconds | 80 |
----------------------------------------
This is basically an accumulation from 0 time to multiples of 5.for last 5 seconds basically i am calculating the amount for the whole day up to the time when i execute this query and for example the amount for whole day before this time was 50 so result table should look like
----------------------------------------
|0 to 5 seconds | 30 + 50 = 80 |
----------------------------------------
|0 to 10 seconds | 80 + 80 = 160 |
----------------------------------------

you can try something like this.
Input Data
DECLARE #Orders TABLE
(
OrderId INT,
CreateStamp DATETIME,
TotalAmount NUMERIC(9,2)
)
INSERT INTO #Orders
SELECT 1,'2015-03-22 15:26:05.620',400
UNION ALL SELECT 2,'2015-03-22 15:26:04.653',500
UNION ALL SELECT 3,'2015-03-22 15:26:05.660',600
UNION ALL SELECT 4,'2015-03-22 15:26:06.663',700
UNION ALL SELECT 5,'2015-03-22 15:26:06.670',900
UNION ALL SELECT 6,'2015-03-22 15:26:05.660',600
UNION ALL SELECT 7,'2015-03-22 15:26:09.663',700
UNION ALL SELECT 8,'2015-03-22 15:26:12.670',900
Query
;WITH CTE as
(
SELECT DATEDIFF(minute,0,CreateStamp)totalminutes,Datepart(second, CreateStamp ) / 5 sec,SUM(TotalAmount) TotalAmount
FROM #Orders
GROUP BY DATEDIFF(minute,0,CreateStamp),Datepart(second, CreateStamp) / 5
)
SELECT DATEADD(minute,totalminutes,0) dt,sec,(SELECT SUM(TotalAmount) FROM cte WHERE totalminutes <=c2.totalminutes and sec <=c2.sec)
FROM CTE c2
ORDER BY sec;
I have added a GROUP BY DATEDIFF(minute,0,CreateStamp) to separate seconds for different dates and minutes.

If I understand you correctly:
DECLARE #t TABLE
(
ID INT ,
D DATETIME ,
A MONEY
)
DECLARE #mind DATETIME ,
#maxd DATETIME
INSERT INTO #t
VALUES ( 1, '2015-04-07 13:49:15.000', 5 ),
( 2, '2015-04-07 13:49:17.000', 15 ),
( 3, '2015-04-07 13:49:35.000', 2 ),
( 4, '2015-04-07 13:49:45.000', 4 ),
( 5, '2015-04-07 13:49:49.000', 20 ),
( 6, '2015-04-07 13:50:05.000', 20 ),
( 7, '2015-04-07 13:50:09.000', 3 ),
( 8, '2015-04-07 13:50:09.000', 3 ),
( 9, '2015-04-07 13:50:10.000', 1 ),
( 10, '2015-04-07 13:50:15.000', 1 )
SELECT #mind = MIN(d) ,
#maxd = MAX(d)
FROM #t;
WITH cte
AS ( SELECT #mind AS d
UNION ALL
SELECT DATEADD(ss, 5, d)
FROM cte
WHERE cte.d <= #maxd
)
SELECT cte.d, SUM(A) AS A FROM cte
JOIN #t t ON t.D < cte.d
GROUP BY cte.d
Output:
d A
2015-04-07 13:49:20.000 20.00
2015-04-07 13:49:25.000 20.00
2015-04-07 13:49:30.000 20.00
2015-04-07 13:49:35.000 20.00
2015-04-07 13:49:40.000 22.00
2015-04-07 13:49:45.000 22.00
2015-04-07 13:49:50.000 46.00
2015-04-07 13:49:55.000 46.00
2015-04-07 13:50:00.000 46.00
2015-04-07 13:50:05.000 46.00
2015-04-07 13:50:10.000 72.00
2015-04-07 13:50:15.000 73.00
2015-04-07 13:50:20.000 74.00

Related

SQL Server Fill Month Gaps in Groups

I have a table for example like below:
declare #test table(Aid int, Bid int, CheckMonth date, Avalue decimal(18,2))
insert into #test (Aid, Bid, CheckMonth, Avalue)
values (1, 4, '2014-07-05', 123.00)
,(1, 4, '2014-08-01', 467.00)
,(1, 4, '2014-11-03', 876.00)
,(1, 4, '2014-12-01', 876.00)
,(2, 6, '2016-01-02', 23.00)
,(2, 6, '2016-03-14', 56.00)
,(2, 6, '2016-04-17', 98.00)
,(2, 6, '2016-07-01', 90.00)
I wish to fill the gaps in months (in CheckMonth column above) with 0.00 values (in Avalue column).
Data is grouped by Aid and Bid columns.
The result should look like below:
Aid Bid CheckMonth Avalue
1 4 '2014-07-05' 123.00
1 4 '2014-08-01' 467.00
1 4 '2014-09-01' 0.00 -->inserted
1 4 '2014-10-01' 0.00 -->inserted
1 4 '2014-11-03' 876.00
1 4 '2014-12-01' 876.00
2 6 '2016-01-02' 23.00
2 6 '2016-02-01' 0.00 -->inserted
2 6 '2016-03-14' 56.00
2 6 '2016-04-17' 98.00
2 6 '2016-05-01' 0.00 -->inserted
2 6 '2016-06-01' 0.00 -->inserted
2 6 '2016-07-01' 90.00
Any help is appreciated.
Thanks.
One option uses a recursive query to generate the month starts for each (aid, bid) tuple; you can then left join the generated resultset with the original table:
with cte as (
select
aid,
bid,
datefromparts(year(min(checkMonth)), month(min(checkMonth)), 1) dt,
datefromparts(year(max(checkMonth)), month(max(checkMonth)), 1) maxDt
from #test
group by aid, bid
union all
select
aid,
bid,
dateadd(month, 1, dt),
maxDt
from cte
where dt < maxDt
)
select c.aid, c.bid, coalesce(t.checkMonth, c.dt) checkMonth, coalesce(t.avalue, 0) avalue
from cte c
left join #test t
on t.aid = c.aid
and t.bid = c.bid
and t.checkMonth >= c.dt
and t.checkMonth < dateadd(month, 1, c.dt)
order by c.aid, c.bid, c.dt
Demo on DB Fiddle:
aid | bid | checkMonth | avalue
--: | --: | :--------- | :-----
1 | 4 | 2014-07-05 | 123.00
1 | 4 | 2014-08-01 | 467.00
1 | 4 | 2014-09-01 | 0.00
1 | 4 | 2014-10-01 | 0.00
1 | 4 | 2014-11-03 | 876.00
1 | 4 | 2014-12-01 | 876.00
2 | 6 | 2016-01-02 | 23.00
2 | 6 | 2016-02-01 | 0.00
2 | 6 | 2016-03-14 | 56.00
2 | 6 | 2016-04-17 | 98.00
2 | 6 | 2016-05-01 | 0.00
2 | 6 | 2016-06-01 | 0.00
2 | 6 | 2016-07-01 | 90.00

How can I sum durations grouped by overlapping times in SQL Server

I am trying to create a stored proc in SQL Server 2008.
I have a "Timings" Table (which could have thousands of records):
StaffID | MachineID | StartTime | FinishTime
1 | 1 | 01/01/2018 12:00 | 01/01/18 14:30
2 | 1 | 01/01/2018 12:00 | 01/01/18 13:00
3 | 2 | 01/01/2018 12:00 | 01/01/18 13:00
3 | 2 | 01/01/2018 13:00 | 01/01/18 14:00
4 | 3 | 01/01/2018 12:00 | 01/01/18 12:30
5 | 3 | 01/01/2018 11:00 | 01/01/18 13:30
This shows how long each staff member was working on each machine.
I would like to produce a results table as below:
MachineID | StaffQty | TotalMins
1 | 1 | 90
1 | 2 | 60
2 | 1 | 120
3 | 1 | 120
3 | 2 | 30
This would show how many minutes each machine had only one person using it, how many minutes each machine had 2 people using it etc.
Normally, I would post what I have tried so far, but all my attempts seem to be so far away, I don't think there is much point.
Obviously, I would be very grateful of a complete solution but I would also appreciate even just a little nudge in the right direction.
I think this answers your question:
declare #t table (StaffID int, MachineID int, StartTime datetime2,FinishTime datetime2)
insert into #t(StaffID,MachineID,StartTime,FinishTime) values
(1,1,'2018-01-01T12:00:00','2018-01-01T14:30:00'),
(2,1,'2018-01-01T12:00:00','2018-01-01T13:00:00'),
(3,2,'2018-01-01T12:00:00','2018-01-01T12:30:00')
;With Times as (
select MachineID,StartTime as Time from #t
union
select MachineID,FinishTime from #t
), Ordered as (
select
*,
ROW_NUMBER() OVER (PARTITION BY MachineID ORDER BY Time) rn
from Times
), Periods as (
select
o1.MachineID,o1.Time as StartTime,o2.Time as FinishTime
from
Ordered o1
inner join
Ordered o2
on
o1.MachineID = o2.MachineID and
o1.rn = o2.rn - 1
)
select
p.MachineID,
p.StartTime,
MAX(p.FinishTime) as FinishTime,
COUNT(*) as Cnt,
DATEDIFF(minute,p.StartTime,MAX(p.FinishTime)) as TotalMinutes
from
#t t
inner join
Periods p
on
p.MachineID = t.MachineID and
p.StartTime < t.FinishTime and
t.StartTime < p.FinishTime
group by p.MachineID,p.StartTime
Results:
MachineID StartTime FinishTime Cnt TotalMinutes
----------- --------------------------- --------------------------- ----------- ------------
1 2018-01-01 12:00:00.0000000 2018-01-01 13:00:00.0000000 2 60
1 2018-01-01 13:00:00.0000000 2018-01-01 14:30:00.0000000 1 90
2 2018-01-01 12:00:00.0000000 2018-01-01 12:30:00.0000000 1 30
Hopefully you can see what each of the CTEs is doing. The only place where this may not give you exactly the results you're seeking is if one person's FinishTime is precisely equal to another person's StartTime on the same machine. Should be rare in real data hopefully.
For Sql server 2012+,
Please mention your Sql server version.
Try my script with other sample data.
Please post other sample data if it is not working.
I think my script can be fix for other Test scenario.
create table #temp(StaffID int,MachineID int,StartTime datetime,FinishTime datetime)
insert into #temp VALUES
(1, 1,'01/01/2018 12:00','01/01/18 14:30')
,(2, 1,'01/01/2018 12:00','01/01/18 13:00')
,(3, 2,'01/01/2018 12:00','01/01/18 12:30')
;
WITH CTE
AS (
SELECT t.*
,t1.StaffQty
,datediff(MINUTE, t.StartTime, t.FinishTime) TotalMinutes
FROM #temp t
CROSS APPLY (
SELECT count(*) StaffQty
FROM #temp t1
WHERE t.machineid = t1.machineid
AND (
t.StartTime >= t1.StartTime
AND t.FinishTime <= t1.FinishTime
)
) t1
)
SELECT MachineID
,StaffQty
,TotalMinutes - isnull(LAG(TotalMinutes, 1) OVER (
PARTITION BY t.MachineID ORDER BY t.StartTime
,t.FinishTime
), 0)
FROM cte t
 
drop table #temp
for Sql server 2008,
;
WITH CTE
AS (
SELECT t.*
,t1.StaffQty
,datediff(MINUTE, t.StartTime, t.FinishTime) TotalMinutes
,ROW_NUMBER() OVER (
PARTITION BY t.machineid ORDER BY t.StartTime
,t.FinishTime
) rn
FROM #temp t
CROSS APPLY (
SELECT count(*) StaffQty
FROM #temp t1
WHERE t.machineid = t1.machineid
AND (
t.StartTime >= t1.StartTime
AND t.FinishTime <= t1.FinishTime
)
) t1
)
SELECT t.MachineID
,t.StaffQty
,t.TotalMinutes - isnull(t1.TotalMinutes, 0) TotalMinutes
FROM cte t
OUTER APPLY (
SELECT TOP 1 TotalMinutes
FROM cte t1
WHERE t.MachineID = t1.machineid
AND t1.rn < t.rn
ORDER BY t1.rn DESC
) t1

SQL Server 2014 Merging Overlapping Date Ranges

I have a table with 200.000 rows in a SQL Server 2014 database looking like this:
CREATE TABLE DateRanges
(
Contract VARCHAR(8),
Sector VARCHAR(8),
StartDate DATE,
EndDate DATE
);
INSERT INTO DateRanges (Contract, Sector, StartDate, Enddate)
SELECT '111', '999', '01-01-2014', '03-31-2014'
union
SELECT '111', '999', '04-01-2014', '06-30-2014'
union
SELECT '111', '999', '07-01-2014', '09-30-2014'
union
SELECT '111', '999', '10-01-2014', '12-31-2014'
union
SELECT '111', '888', '08-01-2014', '08-31-2014'
union
SELECT '111', '777', '08-15-2014', '08-31-2014'
union
SELECT '222', '999', '01-01-2014', '03-31-2014'
union
SELECT '222', '999', '04-01-2014', '06-30-2014'
union
SELECT '222', '999', '07-01-2014', '09-30-2014'
union
SELECT '222', '999', '10-01-2014', '12-31-2014'
union
SELECT '222', '666', '11-01-2014', '11-30-2014'
UNION
SELECT '222', '555', '11-15-2014', '11-30-2014';
As you can see there can be multiple overlaps for each contract and what I would like to have is the result like this
Contract Sector StartDate EndDate
---------------------------------------------
111 999 01-01-2014 07-31-2014
111 888 08-01-2014 08-14-2014
111 777 08-15-2014 08-31-2014
111 999 09-01-2014 12-31-2014
222 999 01-01-2014 10-31-2014
222 666 11-01-2014 11-14-2014
222 555 11-15-2014 11-30-2014
222 999 12-01-2014 12-31-2014
I can not figure out how this can be done and the examples i have seen on this site quite do not fit my problem.
This answer makes use of a few different techniques. The first is a recursive-cte that creates a table with every relevant cal_date which then gets cross apply'd with unique Contract values to get every combination of both values. The second is window-functions such as lag and row_number to determine a variety of things detailed in the comments below. Lastly, and probably most importantly, gaps-and-islands to determine when one Contract/Sector combination ends and the next begins.
Answer:
--determine range of dates
declare #bgn_dt date = (select min(StartDate) from DateRanges)
, #end_dt date = (select max(EndDate) from DateRanges)
--use a recursive CTE to create a record for each day / Contract
; with dates as
(
select #bgn_dt as cal_date
union all
select dateadd(d, 1, a.cal_date) as cal_date
from dates as a
where a.cal_date < #end_dt
)
select d.cal_date
, c.Contract
into #contract_dates
from dates as d
cross apply (select distinct Contract from DateRanges) as c
option (maxrecursion 0)
--Final Select
select f.Contract
, f.Sector
, min(f.cal_date) as StartDate
, max(f.cal_date) as EndDate
from (
--Use the sum-over to obtain the Island Numbers
select dr.Contract
, dr.Sector
, dr.cal_date
, sum(dr.IslandBegin) over (partition by dr.Contract order by dr.cal_date asc) as IslandNbr
from (
--Determine if the record is the start of a new Island
select a.Contract
, a.Sector
, a.cal_date
, case when lag(a.Sector, 1, NULL) over (partition by a.Contract order by a.cal_date asc) = a.Sector then 0 else 1 end as IslandBegin
from (
--Determine which Contract/Date combinations are valid, and rank the Sectors that are in effect
select cd.cal_date
, dr.Contract
, dr.Sector
, dr.EndDate
, row_number() over (partition by dr.Contract, cd.cal_date order by dr.StartDate desc) as ConractSectorRnk
from #contract_dates as cd
left join DateRanges as dr on cd.Contract = dr.Contract
and cd.cal_date between dr.StartDate and dr.EndDate
) as a
where a.ConractSectorRnk = 1
and a.Contract is not null
) as dr
) as f
group by f.Contract
, f.Sector
, f.IslandNbr
order by f.Contract asc
, min(f.cal_date) asc
Output:
+----------+--------+------------+------------+
| Contract | Sector | StartDate | EndDate |
+----------+--------+------------+------------+
| 111 | 999 | 2014-01-01 | 2014-07-31 |
| 111 | 888 | 2014-08-01 | 2014-08-14 |
| 111 | 777 | 2014-08-15 | 2014-08-31 |
| 111 | 999 | 2014-09-01 | 2014-12-31 |
| 222 | 999 | 2014-01-01 | 2014-10-31 |
| 222 | 666 | 2014-11-01 | 2014-11-14 |
| 222 | 555 | 2014-11-15 | 2014-11-30 |
| 222 | 999 | 2014-12-01 | 2014-12-31 |
+----------+--------+------------+------------+

(T-SQL) How to query an audit table, and find changes between 2 dates

The audit table looks like this:
Audit ID VendorID PaymentType CreateDateUTC
999 8048 2 2017-10-30-08:84:24
1000 1234 5 2017-10-31-01:17:34
1001 8048 7 2017-10-31-01:17:45
1002 1234 5 2017-10-31-01:17:53
1003 1234 7 2017-10-31-01:18:23
1004 1234 5 2017-11-01-01:18:45
In this example, you can see that say - VendorID 1234 started as PaymentType 5, then had another entry where it's still 5 (the audit table records additional changes not relevant to my query), then it changes to 7, but then back to 5.
Say I'd want to answer the question: 'Between now and date X, these VendorIDs had a change in PaymentType'. A bonus would be - this was the previous PaymentType.
Expected Results:
VendorID PaymentType Prev_PaymentType
8048 7 2
So say if I queried between now and 10-31-01:00:00, I'd want it to return VendorID 8048 as having changed (and as a bonus, that it's previous PaymentType was 2), but VendorID 1234 shouldn't show up, since at 2017-10-31-01:00:00 it was a 5, and now is still a 5, despite the intermittent changes.
How would one go about querying the VendorIDs whose payment type changed between 2 dates?
Thanks!
Here is an alternative approach that my prove useful, using OUTER APPLY. Note that the AuditID column is used as a tie-breaker mostly because the sample data does not have datetime values.
SQL Fiddle
CREATE TABLE AuditTable (
AuditID int
, VendorID int
, PaymentType int
, CreateDateUTC date
);
INSERT INTO AuditTable
VALUES (999, 8048, 2, '2017-10-30'),
(1000, 1234, 5, '2017-10-31'),
(1001, 8048, 7, '2017-10-31'),
(1002, 1234, 5, '2017-10-31'),
(1003, 1234, 7, '2017-10-31'),
(1004, 1234, 5, '2017-11-01');
Query 1:
select
*
from AuditTable a
outer apply (
select top(1) PaymentType, CreateDateUTC
from AuditTable t
where a.VendorID = t.VendorID
and a.CreateDateUTC >= t.CreateDateUTC
and a.AuditID > t.AuditID
order by CreateDateUTC DESC, AuditID DESC
) oa (PrevPaymentType, PrevDate)
order by
vendorid
, CreateDateUTC
Results:
| AuditID | VendorID | PaymentType | CreateDateUTC | PrevPaymentType | PrevDate |
|---------|----------|-------------|---------------|-----------------|------------|
| 1000 | 1234 | 5 | 2017-10-31 | (null) | (null) |
| 1002 | 1234 | 5 | 2017-10-31 | 5 | 2017-10-31 |
| 1003 | 1234 | 7 | 2017-10-31 | 5 | 2017-10-31 |
| 1004 | 1234 | 5 | 2017-11-01 | 7 | 2017-10-31 |
| 999 | 8048 | 2 | 2017-10-30 | (null) | (null) |
| 1001 | 8048 | 7 | 2017-10-31 | 2 | 2017-10-30 |
CREATE TABLE AuditTable (
AuditID INT,
VendorID INT,
PaymentType INT,
CreateDateUTC DATE
);
INSERT INTO AuditTable VALUES
(999 , 8048, 2, '2017-10-30'),
(1000, 1234, 5, '2017-10-31'),
(1001, 8048, 7, '2017-10-31'),
(1002, 1234, 5, '2017-10-31'),
(1003, 1234, 7, '2017-10-31'),
(1004, 1234, 5, '2017-11-01');
WITH CTE AS (
SELECT *,
ROW_NUMBER () OVER (PARTITION BY CreateDateUTC ORDER BY PaymentType) AS N1
FROM AuditTable
WHERE CreateDateUTC <= '2017-11-02' AND CreateDateUTC >= '2017-10-01'
) ,
MAXP AS(
SELECT VendorID, PaymentType, CreateDateUTC
FROM CTE
WHERE N1 = (SELECT MAX(N1) FROM CTE)
)
SELECT TOP 1 MAXP.VendorID, MAXP.PaymentType AS PaymentType, CTE.PaymentType AS Prev_PaymentType
FROM MAXP
JOIN CTE ON CTE.VendorID = MAXP.VendorID;
Result:
+----------+-------------+------------------+
| VendorID | PaymentType | Prev_PaymentType |
+----------+-------------+------------------+
| 8048 | 7 | 2 |
+----------+-------------+------------------+
Demo
Here is a variant without using LEAD() or LAG() but does use ROW_NUMBER and COUNT() OVER().
See this verision work at:SQL Fiddle
CREATE TABLE AuditTable (
AuditID int
, VendorID int
, PaymentType int
, CreateDateUTC date
);
INSERT INTO AuditTable
VALUES (999, 8048, 2, '2017-10-30'),
(1000, 1234, 5, '2017-10-31'),
(1001, 8048, 7, '2017-10-31'),
(1002, 1234, 5, '2017-10-31'),
(1003, 1234, 7, '2017-10-31'),
(1004, 1234, 5, '2017-11-01');
Query 1:
WITH
rowz AS (
SELECT *
, ROW_NUMBER() OVER (PARTITION BY VendorID
ORDER BY CreateDateUTC, AuditID) AS lagno
FROM AuditTable
),
cte AS (
SELECT *
, ROW_NUMBER() OVER (PARTITION BY VendorID, CreateDateUTC
ORDER BY c DESC, span_dt) rn
FROM (
SELECT r1.AuditID, r1.VendorID, r1.CreateDateUTC
, r1.PaymentType AS prevpaymenttype
, r2.PaymentType
, COALESCE(r2.CreateDateUTC, CAST(GETDATE() AS date)) span_dt
, COUNT(*) OVER (PARTITION BY r1.VendorID, r1.CreateDateUTC, r1.PaymentType) c
FROM rowz r1
LEFT JOIN rowz r2 ON r1.VendorID = r2.VendorID
AND r1.lagno = r2.lagno - 1
) d
)
SELECT
AuditID, VendorID, PrevPaymentType, PaymentType, CreateDateUTC
FROM (
SELECT
*
FROM cte
WHERE ('20171031' BETWEEN CreateDateUTC AND span_dt AND rn = 1)
OR (CAST(GETDATE() AS date) BETWEEN CreateDateUTC AND span_dt AND rn = 1)
) d
WHERE PaymentType <> PrevPaymentType
Results:
| AuditID | VendorID | PrevPaymentType | PaymentType | CreateDateUTC |
|---------|----------|-----------------|-------------|---------------|
| 999 | 8048 | 2 | 7 | 2017-10-30 |

select query to get first row from rows having multiple id's.(without partition by)

id date amount documentNo paperID
1 2015/10/15 500 1234 34
1 2015/10/15 100 1332 33
2 2015/10/13 200 1302 21
2 2015/10/13 400 1332 33
3 2015/11/23 500 1332 43
I should get the output as:
id date amount documentNo paperID
1 2015/10/15 500 1234 34
2 2015/10/13 200 1302 21
3 2015/11/23 500 1332 43
Please suggest a simple select query to fetch only one row without partition by. Note: the date remain same for a particular id.
Try a null-self-join. Basically you are comparing each row to some other version of that row ,but, via an inequality (here I have used documentNo) you end-up with a single row that has no match.
See this SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE Table1
(`id` int, `date` datetime, `amount` int, `documentNo` int, `paperID` int)
;
INSERT INTO Table1
(`id`, `date`, `amount`, `documentNo`, `paperID`)
VALUES
(1, '2015-10-15 00:00:00', 500, 1234, 34),
(1, '2015-10-15 00:00:00', 100, 1332, 33),
(2, '2015-10-13 00:00:00', 200, 1302, 21),
(2, '2015-10-13 00:00:00', 400, 1332, 33),
(3, '2015-11-23 00:00:00', 500, 1332, 43)
;
Query 1:
SELECT
t1.*
FROM table1 AS t1
LEFT OUTER JOIN table1 AS t2 ON t1.id = t2.id
AND t1.date = t2.date
AND t2.documentNo < t1.documentNo
WHERE t2.ID IS NULL
Results:
| id | date | amount | documentNo | paperID |
|----|----------------------------|--------|------------|---------|
| 1 | October, 15 2015 00:00:00 | 500 | 1234 | 34 |
| 2 | October, 13 2015 00:00:00 | 200 | 1302 | 21 |
| 3 | November, 23 2015 00:00:00 | 500 | 1332 | 43 |
EDIT: There are several approaches to this problem even without windowing functions such as row_number() , here is a previous answer covering some MySQL specific alternatives.

Resources