I have one table containing columns: PurchaseOrderID, CompanyID and CreatedDate. I want a column named PONo in this table that will automatically have values from previous column like : PO/2016(Year from CreatedDate)/001(value will increment for same year and same company id).
My expected table is as below:
PurchaseOrderID CompanyID PONo CreatedDate
1 1 PO/2016/001 2016-01-31
2 1 PO/2016/002 2016-02-22
3 1 PO/2016/003 2016-05-25
4 2 PO/2016/001 2016-09-1
5 2 PO/2016/002 2016-10-11
6 2 PO/2016/003 2016-12-31
7 1 PO/2017/001 2017-01-31
8 1 PO/2017/002 2017-02-2
9 1 PO/2017/003 2017-05-20
10 2 PO/2017/001 2017-06-25
11 2 PO/2017/002 2017-07-15
12 2 PO/2017/003 2017-08-22
From This table I want to generate and update PONo like above table.
I want query to generate PONo.
When I insert new record in table then PONo generates automatically from this record.
Note: If need to add any column let me know.
You may looking for this
WITH CTE AS(
SELECT PurchaseOrderID,
CompanyID,
CreatedDate,
ROW_NUMBER() OVER (PARTITION BY CompanyID,YEAR(CreatedDate) ORDER BY CreatedDate) AS RN
FROM TableName
)
SELECT PurchaseOrderID,
CompanyID,
'PO/'+CAST(YEAR(CreatedDate) AS VARCHAR(5))+'/'+RIGHT('00'+CAST(RN AS VRACHAR(5),3)),
CreatedDate
FROM CTE
Give this a try...
IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL
DROP TABLE #TestData;
CREATE TABLE #TestData (
PurchaseOrderID int NOT NULL PRIMARY KEY,
CompanyID int NOT NULL,
PONo CHAR(11) NULL,
CreatedDate DATE NOT NULL
);
INSERT #TestData(PurchaseOrderID, CompanyID, CreatedDate) VALUES
(1 , 1, '2016-01-31'),
(2 , 1, '2016-02-22'),
(3 , 1, '2016-05-25'),
(4 , 2, '2016-09-01'),
(5 , 2, '2016-10-11'),
(6 , 2, '2016-12-31'),
(7 , 1, '2017-01-31'),
(8 , 1, '2017-02-02'),
(9 , 1, '2017-05-20'),
(10, 2, '2017-06-25'),
(11, 2, '2017-07-15'),
(12, 2, '2017-08-22');
-- SELECT * FROM #TestData td;
--=========================================
SELECT
*,
PONo = CONCAT('PO/', YEAR(td.CreatedDate), '/', RIGHT(CONCAT('000',
ROW_NUMBER() OVER (PARTITION BY td.CompanyID, YEAR(td.CreatedDate) ORDER BY td.PurchaseOrderID)), 3))
FROM
#TestData td;
Results...
PurchaseOrderID CompanyID PONo CreatedDate PONo
--------------- ----------- ----------- ----------- -------------------
1 1 NULL 2016-01-31 PO/2016/001
2 1 NULL 2016-02-22 PO/2016/002
3 1 NULL 2016-05-25 PO/2016/003
7 1 NULL 2017-01-31 PO/2017/001
8 1 NULL 2017-02-02 PO/2017/002
9 1 NULL 2017-05-20 PO/2017/003
4 2 NULL 2016-09-01 PO/2016/001
5 2 NULL 2016-10-11 PO/2016/002
6 2 NULL 2016-12-31 PO/2016/003
10 2 NULL 2017-06-25 PO/2017/001
11 2 NULL 2017-07-15 PO/2017/002
12 2 NULL 2017-08-22 PO/2017/003
If you want to generate new sequence logic.
CREATE TABLE PO_wise_seq
(
CompanyID BIGINT,
year_ INT,
seq BIGINT IDENTITY(1,1)
)
DECLARE #CompanyID BIGINT =332
DECLARE #Year_id BIGINT =2016
INSERT INTO PO_wise_seq VALUES (#CompanyID,#Year_id)
select CompanyID
,cast(#CompanyID as nvarchar) +'/' +cast(#Year_id as nvarchar)+'/'+cast(count(1) as nvarchar) as seq
FROM PO_wise_seq
WHERE CompanyID=#CompanyID
AND year_=#Year_id
GROUP BY CompanyID,year_
If you want to generate new sequence logic.
CREATE TABLE PO_wise_seq
(
PO BIGINT,
year_ INT,
seq BIGINT IDENTITY(1,1)
)
DECLARE #PO_ID BIGINT =332
DECLARE #Year_id BIGINT =2016
INSERT INTO PO_wise_seq VALUES (#PO_ID,#Year_id)
select PO,
cast(#PO_ID as nvarchar) +'/' +cast(#Year_id as nvarchar)+'/'+cast(count(1) as nvarchar) as seq
FROM PO_wise_seq
WHERE PO=#PO_ID
AND year_=#Year_id
GROUP BY PO,year_
Related
Let's say that we have 2 tables named Records and Opportunities:
Records:
RecordID
CustomerID
CreateDate
777
1
1/1/2021
888
2
1/1/2021
999
1
2/1/2021
Opportunities:
OppID
CustomerID
OppCreateDate
10
1
12/31/2020
11
1
1/10/2021
12
2
2/1/2021
13
1
4/1/2021
14
1
8/5/2025
Desired Output:
RecordID
CustomerID
CreateDate
#Opportunities
777
1
1/1/2021
1
888
2
1/1/2021
1
999
1
2/1/2021
1
As you can see, the Records table provides the first 3 columns of the desired output, and the "#Opportunities" column is created by counting the number of opportunities that happen after the record is created for a given customer.
Two key things to note on this logic:
Only count opportunities when they occur within 6 months of a record.
If another record is created for a customer, only count opportunities for the most recent record.
More specifically, OppID = 11 will get credited to RecordID = 777; 12 to 888; and 13 to 999. 10 and 14 will not get credited to either RecordID.
I wrote the below code, which does not take into account #2 above:
CREATE TABLE #Records
(
RecordID int
, CustomerID int
, CreateDate Date
)
INSERT INTO #Records
VALUES
(777, 1, '2021-01-01')
, (888, 2, '2021-01-31')
, (999, 1, '2021-02-01')
CREATE TABLE #Opportunities
(
OppID int
, CustomerID int
, OppCreateDate Date
)
INSERT INTO #Opportunities
VALUES
(10, 1, '2020-12-31')
, (11, 1, '2021-01-10')
, (12, 2, '2021-02-01')
, (13, 1, '2021-04-01')
, (14, 1, '2025-08-25')
select *
from #Records
select *
from #Opportunities
select rec.*
, (select count(*)
from #Opportunities opp
where rec.CustomerID=opp.CustomerID
and rec.CreateDate<=opp.OppCreateDate --record happened on the same day or before the opportunity
and datediff(month,rec.CreateDate,opp.OppCreateDate) < 6 --opened and created within 6 months
) as [#Opportunities]
from #Records rec
Any suggestions to incorporate #2 above and generate the desired output?
Decide on which #records row is related to an #Opportunities row based on #records.CreateDate
select RecordID, CustomerID, CreateDate, count(*) cnt
from (
select r.RecordID, r.CustomerID, r.CreateDate,
row_number() over(partition by op.OppID order by r.CreateDate desc) rn
from #records r
join #Opportunities op on r.CustomerID = op.CustomerID and datediff(month, r.CreateDate, op.OppCreateDate) < 6 and r.CreateDate <= op.OppCreateDate
) t
where rn = 1
group by RecordID, CustomerID, CreateDate
Returns
RecordID CustomerID CreateDate cnt
777 1 2021-01-01 1
888 2 2021-01-31 1
999 1 2021-02-01 1
Try this:
DECLARE #Records table ( RecordID int, CustomerID int, CreateDate date );
INSERT INTO #Records VALUES
( 777, 1, '2021-01-01' ), ( 888, 2, '2021-01-31' ), ( 999, 1, '2021-02-01' );
DECLARE #Opportunities table ( OppID int, CustomerID int, OppCreateDate date );
INSERT INTO #Opportunities VALUES
( 10, 1, '2020-12-31' )
, ( 11, 1, '2021-01-10' )
, ( 12, 2, '2021-02-01' )
, ( 13, 1, '2021-04-01' )
, ( 14, 1, '2025-08-25' );
SELECT
*
FROM #Records r
OUTER APPLY (
SELECT
COUNT ( * ) AS [#Opportunities]
FROM #Opportunities AS o
WHERE
o.CustomerID = r.CustomerID
AND o.OppCreateDate >= r.CreateDate
AND DATEDIFF ( month, r.CreateDate, o.OppCreateDate ) <= 6
AND o.OppID NOT IN (
SELECT
OppID
FROM #Records AS r2
INNER JOIN #Opportunities AS o2
ON r2.CustomerID = o2.CustomerID
WHERE
r2.CustomerID = o.CustomerID
AND o2.OppCreateDate >= r2.CreateDate
AND r2.RecordID > r.RecordID
)
) AS Opps
ORDER BY
r.RecordID;
RETURNS
+----------+------------+------------+----------------+
| RecordID | CustomerID | CreateDate | #Opportunities |
+----------+------------+------------+----------------+
| 777 | 1 | 2021-01-01 | 1 |
| 888 | 2 | 2021-01-31 | 1 |
| 999 | 1 | 2021-02-01 | 1 |
+----------+------------+------------+----------------+
There are two table:
Table persons:
P_id Name BirthDate
1 N1 2016-08-02
2 N2 2015-05-02
3 N3 2013-06-01
4 N4 2014-01-09
Table visited:(p_id is foreign key to table persons)
Id. Visitor_id. P_id. Visit_date
1 10 1 2017-03-05
2 11 2 2017-01-01
3 10 2 2017-02-03
4 12 3 2016-05-07
5 11 4 2016-04-09
6 10 1 2017-04-09
We are going to get the count of visited persons who their old are under 1, between 1 and 2, between 2 and 3 at date of visit_date by each visitor_id.
The results like :
Visitor_id Under_one Bet_one_two Bet_two_three
10 2 1 0
11 0 1 1
12 0 0 1
Could anyone help me how write a query in sql server for getting the results?
In above results, 0,1,2 means that we subtract of two date(visited_date - birthdate), for example : the result of 2013/03/05 - 2011/06/07 is between 1 and 2
you can try a pivot query like below
select
visitor_id,
Under_one=ISNULL([0],0),
Bet_one_two=ISNULL([1],0),
Bet_two_three=ISNULL([2],0)
from
(
select visitor_id, datediff(m,BirthDate,visit_date)/12 age_in_years,count(1) count from persons p join
visited v on p.p_id=v.p_id
group by visitor_id,datediff(m,BirthDate,visit_date)/12
) src
pivot
(
max(count) for age_in_years in ([0],[1],[2])
)p
see live demo
/*
DROP TABLE Visited
DROP TABLE Persons
DROP TABLE #Data
DROP TABLE #Results
*/
CREATE TABLE Persons
(
[P_id.] INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
[Name] NVARCHAR(2),
BirthDate DATETIME
)
INSERT INTO PERSONS ([Name],BirthDate) VALUES ('N1','2016-08-02')
INSERT INTO PERSONS ([Name],BirthDate) VALUES ('N2','2015-05-02')
INSERT INTO PERSONS ([Name],BirthDate) VALUES ('N3','2013-06-01')
INSERT INTO PERSONS ([Name],BirthDate) VALUES ('N4','2014-01-09')
GO
CREATE TABLE Visited
(
[ID.] INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
[Visitor_id.] INT,
[P_id.] INT REFERENCES Persons,
Visit_date DATETIME
)
GO
INSERT INTO Visited ([Visitor_id.],[P_id.],Visit_date) VALUES (10,1,'2017-03-05')
INSERT INTO Visited ([Visitor_id.],[P_id.],Visit_date) VALUES (11,2,'2017-01-01')
INSERT INTO Visited ([Visitor_id.],[P_id.],Visit_date) VALUES (10,2,'2017-02-03')
INSERT INTO Visited ([Visitor_id.],[P_id.],Visit_date) VALUES (12,3,'2016-05-07')
INSERT INTO Visited ([Visitor_id.],[P_id.],Visit_date) VALUES (11,4,'2016-04-09')
INSERT INTO Visited ([Visitor_id.],[P_id.],Visit_date) VALUES (10,1,'2017-04-09')
GO
SELECT [Visitor_id.],
CASE WHEN DATEPART(YY,v.visit_date-p.birthdate) = 1900 THEN 'Under_one'
WHEN DATEPART(YY,v.visit_date-p.birthdate) = 1901 THEN 'Bet_one_two'
WHEN DATEPART(YY,v.visit_date-p.birthdate) = 1902 THEN 'Bet_two_three'
END AS Age,
COUNT([Visitor_id.]) AS Number
INTO #Data
FROM Persons p INNER JOIN Visited v on p.[P_id.]=v.[P_id.]
GROUP BY [Visitor_id.],DATEPART(YY,v.visit_date-p.birthdate)
GO
CREATE TABLE #Results
(
Visitor_ID INT,
Under_one INT,
Bet_one_two INT,
Bet_two_three INT
)
GO
DECLARE #Visitor_id INT = (SELECT MIN([Visitor_id.]) FROM #Data)
WHILE #Visitor_id <= (SELECT MAX([Visitor_id.]) FROM #Data)
BEGIN
INSERT INTO #Results VALUES
(
(SELECT #Visitor_id)
,
(SELECT Number FROM #Data WHERE [Visitor_id.]=#Visitor_id AND Age = 'Under_one')
,
(SELECT Number FROM #Data WHERE [Visitor_id.]=#Visitor_id AND Age = 'Bet_one_two')
,
(SELECT Number FROM #Data WHERE [Visitor_id.]=#Visitor_id AND Age = 'Bet_two_three')
)
SET #Visitor_id = #Visitor_id + 1
END
UPDATE #Results SET Under_one = 0 WHERE Under_one IS NULL
GO
UPDATE #Results SET Bet_one_two = 0 WHERE Bet_one_two IS NULL
GO
UPDATE #Results SET Bet_two_three = 0 WHERE Bet_two_three IS NULL
GO
SELECT * FROM #Results
How about something like:
CREATE TABLE persons
(p_id int, name varchar(5), birthday date);
INSERT INTO persons
(p_id, name, birthday)
VALUES
(1, 'N1', '2016-08-02'),
(2, 'N2', '2015-05-02'),
(3, 'N3', '2013-06-01'),
(4, 'N4', '2014-01-09');
CREATE TABLE visited
(id int, visitor_id int,p_id int, visit_date date)
;
INSERT INTO visited(id, visitor_id,p_id, visit_date)
VALUES
(1,10,1,'2017-03-05'),
(2,11,2,'2017-01-01'),
(3,10,2,'2017-02-03'),
(4,12,3,'2016-05-07'),
(5,11,4,'2016-04-09'),
(6,10,1,'2017-04-09');
WITH visitAge(visitor_ID, VisitAge) AS
(SELECT
v.visitor_ID, DateDiff(Year, birthday,visit_date) as VisitAge
FROM visited v
INNER JOIN persons p on v.p_ID = p.p_ID
)
SELECT
visitor_ID,
SUM(CASE WHEN VisitAge < 1 THEN 1 ELSE 0 END ) AS under_one,
SUM(CASE WHEN VisitAge >= 1 AND VisitAge < 2 THEN 1 ELSE 0 END ) AS Bet_one_two,
SUM(CASE WHEN VisitAge >= 2 AND VisitAge < 3 THEN 1 ELSE 0 END ) AS Bet_two_three
FROM
visitAge
GROUP BY visitor_ID;
not durable solution...but for what I see in the question...it's a start for you....
SQL Fiddle link
I need to get all the consecutive top row where a column value is equal between them
my table is:
CREATE TABLE [dbo].[Items](
[Id] [int] NOT NULL,
[IdUser] [int] NOT NULL,
[CreatedDate] [datetime] NOT NULL,
[SomeData] nvarchar(50) NOT NULL);
and i want the top rows (ordered by Id desc) with the same IdUser
if table data is:
Id IdUser CreatedDate SomeData
--- ------- ------------------------ --------
1 1 2017-09-21T09:42:01.407Z sdafsasfa
2 1 2017-09-21T09:42:01.407Z sdafsasfa
4 2 2017-09-21T09:42:01.41Z sdafsasfa
5 3 2017-09-21T09:42:01.41Z sdafsasfa
7 3 2017-09-21T09:42:01.413Z sdafsasfa
8 3 2017-09-21T09:42:01.413Z sdafsasfa
9 10 2017-09-21T09:42:01.417Z sdafsasfa
11 11 2017-09-21T09:42:01.417Z sdafsasfa
12 2 2017-09-21T09:42:01.42Z sdafsasfa
15 2 2017-09-21T09:42:01.42Z sdafsasfa
I want :
Id IdUser CreatedDate SomeData
--- ------- ------------------------ --------
12 2 2017-09-21T09:42:01.42Z sdafsasfa
15 2 2017-09-21T09:42:01.42Z sdafsasfa
if table data is:
Id IdUser CreatedDate SomeData
--- ------- ------------------------ --------
1 1 2017-09-21T09:42:01.407Z sdafsasfa
2 1 2017-09-21T09:42:01.407Z sdafsasfa
4 2 2017-09-21T09:42:01.41Z sdafsasfa
I want :
Id IdUser CreatedDate SomeData
--- ------- ------------------------ --------
4 2 2017-09-21T09:42:01.41Z sdafsasfa
SqlFiddle
you can try this query:
select I.*
from
[dbo].[Items] I
JOIN
(select top 1 Id, IdUser from [dbo].[Items] order by Id desc)I2
on I.Iduser=I2.Iduser
order by Id desc;-- this can be removed to remove ordering by Id Desc
updated fiddle link
You could use LAG and SUM() OVER() like this
DECLARE #Items as Table
(
[Id] [int] NOT NULL,
[IdUser] [int] NOT NULL,
[CreatedDate] [datetime] NOT NULL,
[SomeData] nvarchar(50) NOT NULL
);
INSERT INTO #Items
(
Id,
IdUser,
CreatedDate,
SomeData
)
VALUES
( 1 , 1 ,getdate(),'sdafsasfa'),
( 2 , 1 ,getdate(),'sdafsasfa'),
( 4 , 2 ,getdate(),'sdafsasfa'),
( 5 , 3 ,getdate(),'sdafsasfa'),
( 7 , 3 ,getdate(),'sdafsasfa'),
( 8 , 3 ,getdate(),'sdafsasfa'),
( 9 , 10,getdate(),'sdafsasfa'),
( 11, 11,getdate(),'sdafsasfa'),
( 12, 2 ,getdate(),'sdafsasfa'),
( 15, 2 ,getdate(),'sdafsasfa')
;WITH temp AS
(
SELECT *,
CASE
WHEN lag(i.IdUser) over(ORDER BY i.Id) = i.IdUser THEN 0
ELSE 1
END as ChangingPoint
FROM #Items i
),
temp1 AS
(
SELECT
*,
sum(t.ChangingPoint) OVER(ORDER BY t.Id) as GroupId
FROM temp t
)
SELECT TOP 1 WITH TIES
t.Id,
t.IdUser,
t.CreatedDate,
t.SomeData
FROM temp1 t
ORDER BY GroupId DESC
See demo here: http://rextester.com/PHWWU96232
Assuming you want last rows with highest CreateDate and same IdUser then DENSE_RANK will help
SELECT id, iduser, CreatedDate, somedata
FROM (
SELECT id, iduser, CreatedDate, somedata,
DENSE_RANK() OVER (ORDER BY CreatedDate desc, IdUser) ord
FROM [dbo].[Items]) t
WHERE t.ord = 1
The equivalent SQL query is
SELECT *
FROM Items t1
WHERE NOT EXISTS (
SELECT *
FROM Items t2
WHERE t2.createddate > t1.createddate or
(t2.createddate = t1.createddate and t2.iduser < t1.iduser)
)
demo
Despite TriV's solution works fine I ended up using a modified Radim Bača's solution (his solution dont work as i need) because it is faster IMO
SELECT id, iduser, createddate, somedata
FROM Items t1
WHERE NOT EXISTS (
SELECT 1
FROM Items t2
WHERE t2.id > t1.id and t2.iduser <> t1.iduser );
SQLFiddle
select I.*
from
[dbo].[Items1] I
JOIN
(select top 1 Id, IdUser,CreatedDate from [dbo].[Items1] order by Id desc)I2
on I.CreatedDate=I2.CreatedDate
order by Id desc;-- this can be removed to remove ordering by Id Desc
I have a sales table like this
salesmanID customerID productID date
1 100 1 20.02.2015
1 101 2 20.02.2015
1 102 4 21.02.2015
2 122 6 20.02.2015
2 120 2 22.02.2015
3 150 1 23.02.2015
3 144 8 23.02.2015
3 122 4 24.02.2015
and I want to count of daily sales for each salesman day by day between min and max dates of given two dates(in this sample 20-02-2015 and 24-02-2015) like this,
salesmanID 20.02.2015 21.02.2015 22.02.2015 23.02.2015 24.02.2015
1 2 1 0 0 0
2 1 0 1 0 0
3 0 0 0 2 1
How can I do this in SQL query?
you have to use PIVOT and count of SalesmanID
declare #temp table
(salesmanID int, customerID int, productID int, dates VARCHAR(10))
insert into #temp values (1,100,1,CONVERT(VARCHAR(10), '20.02.2015', 104) )
insert into #temp values (1,101,2,CONVERT(VARCHAR(10), '20.02.2015', 104) )
insert into #temp values (1,102,4,CONVERT(VARCHAR(10), '21.02.2015', 104) )
insert into #temp values (2,122,6,CONVERT(VARCHAR(10), '20.02.2015', 104) )
insert into #temp values (2,120,2,CONVERT(VARCHAR(10), '22.02.2015', 104) )
insert into #temp values (3,150,1,CONVERT(VARCHAR(10), '23.02.2015', 104) )
insert into #temp values (3,144,8,CONVERT(VARCHAR(10), '23.02.2015', 104) )
insert into #temp values (3,122,4,CONVERT(VARCHAR(10), '24.02.2015', 104) )
--QUERY
SELECT *
FROM (SELECT salesmanID, salesmanID as id,dates
FROM #temp) as s
PIVOT
(
count(id)
FOR dates IN ([20.02.2015], [21.02.2015], [22.02.2015], [23.02.2015], [24.02.2015])
)AS pivots
RESULT
DateTime -- Unit -- Client --- Qty
03/02/2013 08:00:01 -- 3 -- 1 --- 1
03/02/2013 08:00:02 -- 3 -- 2 --- 1
03/02/2013 08:00:03 -- 3 -- 3 --- 2
03/02/2013 08:00:04 -- 3 -- 3 --- 2
03/02/2013 08:00:05 -- 3 -- 3 --- 5
03/02/2013 08:00:06 -- 3 -- 3 --- 4
03/02/2013 08:00:07 -- 3 -- 4 --- 6
03/02/2013 08:00:08 -- 3 -- 4 --- 67
03/02/2013 08:00:09 -- 3 -- 4 --- 76
03/02/2013 08:00:10 -- 3 -- 4 --- 76
And I want :
DateTime -- Unit -- Client --- Qty
03/02/2013 08:00:01 -- 3 -- 1 --- 1
03/02/2013 08:00:02 -- 3 -- 2 --- 1
03/02/2013 08:00:03 -- 3 -- 3 --- 2
03/02/2013 08:00:05 -- 3 -- 3 --- 5
03/02/2013 08:00:07 -- 3 -- 4 --- 6
03/02/2013 08:00:09 -- 3 -- 4 --- 76
The criteria to filter is get the min and max "Qty" from table and get only the first value when exists duplicate "Qty" values in the same "Unit" and "client" column.
I do the follow T-SQL, but the retrieval is the last "Qty" value when the "Unit" and "client" column are the same, I need the first.
--1
CREATE TABLE Transact
(DateTime DateTime,
Unit INT NULL,
Client INT NULL,
Qty INT NULL
)
INSERT INTO Transact (Datetime,Unit,Client,Qty)
Values ( '03/02/2013 08:00:01',3,1,1)
Values ( '03/02/2013 08:00:02',3,2,1)
Values ( '03/02/2013 08:00:03',3,3,2)
Values ( '03/02/2013 08:00:04',3,3,2)
Values ( '03/02/2013 08:00:05',3,3,5)
Values ( '03/02/2013 08:00:06',3,3,4)
Values ( '03/02/2013 08:00:07',3,4,6)
Values ( '03/02/2013 08:00:08',3,4,67)
Values ( '03/02/2013 08:00:09',3,4,76)
Values ( '03/02/2013 08:00:10',3,4,76)
DECLARE #Total TABLE
(DateTime DateTime,
Unit INT NULL,
Client INT NULL,
Qty INT NULL
)
DECLARE #Uniques TABLE
(DateTime DateTime,
Unit INT NULL,
Client INT NULL,
Qty INT NULL
)
DECLARE #Mini TABLE
(DateTime DateTime,
Unit INT NULL,
Client INT NULL,
Qty INT NULL
)
DECLARE #Maxi TABLE
(DateTime DateTime,
Unit INT NULL,
Client INT NULL,
Qty INT NULL
)
--2
INSERT INTO #Total SELECT * FROM Transact
INSERT INTO #Mini SELECT MIN(Datetime) Datetime,Unit,Client,MIN(Qty) FROM #Total GROUP BY Unit,Client
INSERT INTO #Maxi SELECT MAX(Datetime) Datetime,Unit,Client,MAX(Qty) FROM #Total GROUP BY Unit,Client
--3
INSERT INTO #Uniques SELECT * FROM #Mini UNION SELECT * FROM #Maxi
SELECT * FROM #Uniques
Thanks in advance.
Pablo Geronimo.
Try this:
WITH MinCTE
AS
(
SELECT *,
ROW_NUMBER() OVER(Unit, PARTITION BY Client
ORDER BY Qty, DateTime ) AS RN
FROM Transact
), MaxCTE
AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY Unit, Client
ORDER BY Qty DESC, DateTime) AS RN
FROM Transact
)
SELECT DateTime, Unit, Client, Qty FROM MinCTE WhERE RN = 1
UNION
SELECT DateTime, Unit, Client, Qty FROM MaxCTE WhERE RN = 1;
SQL Fiddle demo
Here's what you can try:
SELECT DISTINCT MIN(DateTime), MIN(Qty), Unit, Client FROM Transact
GROUP BY Unit, Client
UNION
SELECT DISTINCT MAX(DateTime), MAX(Qty), Unit, Client FROM Transact
GROUP BY Unit, Client
First select the records with min and max Qty to a single table, and then select the min DateTime for those records.
SELECT MIN(DateTime), [Transact].Unit, [Transact].Client, [Transact].Qty
FROM (
SELECT DISTINCT Unit, Client, MIN(Qty) as Qty
FROM [Transact]
GROUP BY Unit, Client
UNION
SELECT Unit, Client, MAX(Qty)
FROM [Transact]
GROUP BY Unit, Client
) as MinMax
JOIN [Transact] ON [Transact].Unit = MinMax.Unit AND [Transact].Client = MinMax.Client AND [Transact].Qty = MinMax.Qty
GROUP BY [Transact].Unit, [Transact].Client, [Transact].Qty
I used a subquery but isn’t hard to change it to a memory table if you prefer.