I have a table and there are 4 fields in it, ID, Price, QTY, Ratting and Optional [Position].
I have all the records Grouped By Columns [Qty,Ratting]
I have to define the position of groupwise and store that Position into Optional column.
For better understanding I have added an image with data in table:
On the basis of QTY in Each Rating I have to Mark Top3, Bottom3 and Rest of them as remaining.
I am not getting how to do it.
Can anybody suggest me how to do it?
So far what I've tried is:
Declare #RankTable TABLE
(
ID INT,
Price Decimal (10,2),
Qty INT,
Ratting INT
)
INSERT INTO #RankTable
SELECT 1,10,15,1
UNION ALL
SELECT 2,11,11,1
UNION ALL
SELECT 3,96,10,1
UNION ALL
SELECT 4,96,8,1
UNION ALL
SELECT 5,56,7,1
UNION ALL
SELECT 6,74,5,1
UNION ALL
SELECT 7,93,4,1
UNION ALL
SELECT 8,98,2,1
UNION ALL
SELECT 9,12,1,1
UNION ALL
SELECT 10,32,80,2
UNION ALL
SELECT 11,74,68,2
UNION ALL
SELECT 12,58,57,2
UNION ALL
SELECT 13,37,43,2
UNION ALL
SELECT 14,79,32,2
UNION ALL
SELECT 15,29,28,2
UNION ALL
SELECT 16,46,17,2
UNION ALL
SELECT 17,86,13,2
UNION ALL
SELECT 19,75,110,3
UNION ALL
SELECT 20,27,108,3
UNION ALL
SELECT 21,38,104,3
UNION ALL
SELECT 22,87,100,3
UNION ALL
SELECT 23,47,89,3
DECLARE #PositionGroup VARCHAR(1)
SELECT *,ISNULL(#PositionGroup,'') AS Position FROM #RankTable
You can try this:
SELECT ID
,Price
,Qty
,Ratting
,CASE WHEN RowID >= 1 AND RowID <= 3
THEN 0
ELSE CASE WHEN RowID > Total - 3 THEN 1 ELSE 2 END END AS Position
FROM (SELECT ID
,Price
,Qty
,Ratting
,COUNT(*) OVER(PARTITION BY Ratting) AS Total
,ROW_NUMBER() OVER(PARTITION BY Ratting ORDER BY Qty DESC) AS RowID
,ISNULL(#PositionGroup,'') AS Position
FROM #RankTable) AS T
Use Window Function. Try this.
;WITH cte
AS (SELECT *,
Row_number()OVER(partition BY rating ORDER BY id) rn,
count(id)OVER(partition BY rating) mx
FROM #RankTable)
SELECT ID,
Price,
Qty,
Rating,
mx - rn,
CASE WHEN rn IN ( 1, 2, 3 ) THEN 0
WHEN mx - rn IN( 0, 1, 2 ) THEN 1
ELSE 2
END position
FROM cte
try this as well.
;WITH cte AS
(
SELECT MAX(Row) [Max],
MIN(Row) [Min],
LU.Ratting
FROM (
SELECT *,
ROW_NUMBER() OVER(PARTITION BY Ratting ORDER BY Qty DESC) Row
FROM #RankTable)LU
GROUP BY LU.Ratting
)
SELECT ID,
R.Price,
R.Qty,
cte.Ratting,
CASE WHEN (Row - Min) <= 2 THEN 0 WHEN (Max - Row) <= 2 THEN 1 ELSE 2 END Position
FROM cte
JOIN (
SELECT Ratting,
ID,
Price,
Qty,
ROW_NUMBER() OVER(PARTITION BY Ratting ORDER BY Qty DESC) [Row]
FROM #RankTable
) R ON R.Ratting = cte.Ratting
Result:
Related
this sounds like a simple question but I just cant find the right way.
given the simplified table
with t as (
select ordernumber, orderdate, case when ordertype in (5,21) then 1 else 0 end is_restore , ordertype, row_number() over(order by orderdate) rn from
(
select to_date('29.08.08','DD.MM.YY') orderdate,'313' ordernumber, 1 as ordertype from dual union all
select to_date('13.03.15','DD.MM.YY') orderdate, '90/4/2' ordernumber, 5 as ordertype from dual
)
)
select * from t -- where clause should be here
for every row is_restore guaranteed to be 1 or 0.
if table has a row where is_restore=1 then select ordernumber,orderdate of that row and nothing else.
If a table does not have a row where is_restore=1 then select ordernumber,orderdate of the row where rn=1(row where rn=1 is guaranteed to exist in a table)
Given the requirements above what do I need to put in where clause to get the following?
You could use ROW_NUMBER:
CREATE TABLE t
AS
select ordernumber, orderdate,
case when ordertype in (5,21) then 1 else 0 end is_restore, ordertype,
row_number() over(order by orderdate) rn
from (
select to_date('29.08.08','DD.MM.YY') orderdate,'313' ordernumber,
1 as ordertype
from dual union all
select to_date('13.03.15','DD.MM.YY') orderdate, '90/4/2' ordernumber,
5 as ordertype
from dual);
-------------------
with cte as (
select t.*,
ROW_NUMBER() OVER(/*PARTITION BY ...*/ ORDER BY is_restore DESC, rn) AS rnk
from t
)
SELECT *
FROM cte
WHERE rnk = 1;
db<>fiddle demo
Here is sql, that doesn't use window functions, maybe it will be useful for those, whose databases don't support OVER ( ... ) or when there are indexed fields, on which query is based.
SELECT
*
FROM t
WHERE t.is_restore = 1
OR (
NOT EXISTS (SELECT 1 FROM t WHERE t.is_restore = 1)
AND t.rn = 1
)
I am trying to insert a new column in a view in SQL Server 2012 to assign a new number to each unique TxnID.
Currently the TxnID is 28 characters long. It would be great if I could assign each TxnID with a new number starting with '1'..
Current TxnID
-------------------------
2010100009000010000006783
2010100009000010000006784
2010100009000010000006785
2010100009000010000006785
Desired TxnID
1
2
3
3
Use ranking function rank() that would be help
select *, rank() over (order by TxnID) TxnID from table
Use ROW_NUMBER()
CREATE VIEW DBO.Vw_MyView
AS
SELECT
TxnID = ROW_NUMBER() OVER(ORDER BY TxnID),
*
FROM YourTable
We can use many methods for this-
--RANK()
SELECT * , RANK() OVER (ORDER BY [Current TxnID]) rowNumx FROM (
SELECT '2010100009000010000006783' [Current TxnID] UNION ALL
SELECT '2010100009000010000006784' UNION ALL
SELECT '2010100009000010000006785' UNION ALL
SELECT '2010100009000010000006785' )p
--DENSE_RANK
SELECT * , DENSE_RANK() OVER (ORDER BY [Current TxnID]) rowNumx FROM (
SELECT '2010100009000010000006783' [Current TxnID] UNION ALL
SELECT '2010100009000010000006784' UNION ALL
SELECT '2010100009000010000006785' UNION ALL
SELECT '2010100009000010000006785' )p
--Other
;WITH CTE AS
(
SELECT '2010100009000010000006783' [Current TxnID] UNION ALL
SELECT '2010100009000010000006784' UNION ALL
SELECT '2010100009000010000006785' UNION ALL
SELECT '2010100009000010000006785'
)
SELECT [Current TxnID], rowNumx = ( SELECT COUNT(*)+1 FROM CTE c1 WHERE c1.[Current TxnID] < c.[Current TxnID] )
FROM CTE c
OUTPUT For all
/*------------------------
OUTPUT
------------------------*/
Current TxnID rowNumx
------------------------- --------------------
2010100009000010000006783 1
2010100009000010000006784 2
2010100009000010000006785 3
2010100009000010000006785 3
(4 row(s) affected)
I have this table:
TableA
----------------
ID (pk) Name
1 A
2 B
3 C
4 A
5 D
6 A
7 B
8 A
9 D
10 C
....
I need to randomly extract with a SELECT TOP 5 ID, Name FROM TableA
with Name that must be unique within the 5 records.
I'm trying :
;WITH group
AS
(
SELECT ID, Name,
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY NewId()) rn
FROM TableA
)
SELECT ID, Name
FROM group
WHERE rn = 1
but every time I have quite the same results.
I need to select between all the values for ID at random, assuring that Name will always be different for each record.
I hope the problem is understandable. Any ideas?
Found a solution. It seems to work!
;WITH group
AS (
SELECT ID, Name, ROW_NUMBER() OVER (PARTITION BY Name ORDER BY NewId()) rn FROM TableA )
SELECT top 5 ID, Name, NewId() [NewId]
FROM group
WHERE rn = 1
ORDER BY [newid]
Perhaps the problem is that although newid() is random, it may tend to be sequential. Does this fix the problem?
WITH g as (
SELECT ID, Name,
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY RAND(CHECKSUM(NewId()))) as rn
FROM TableA
)
SELECT ID, Name
FROM g
WHERE rn = 1;
CREATE TABLE #test(ID INT ,Name VARCHAR(1)) INSERT INTO #test(ID ,Name )
SELECT 1,'A' UNION ALL SELECT 2,'B' UNION ALL SELECT 3,'C' UNION ALL
SELECT 4,'A' UNION ALL SELECT 5,'D'UNION ALL SELECT 6,'A' UNION ALL
SELECT 7,'B' UNION ALL SELECT 8,'A'UNION ALL SELECT 9,'D' UNION ALL
SELECT 10,'C'
SELECT T1.ID ,T1.Name FROM #test T1
JOIN ( SELECT TOP 5 Name FROM #test T2 ORDER BY NEWID()
) A ON T1.Name = A.Name ORDER BY A.Name
;WITH group
AS
(
SELECT ID, Name,
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY NewId()) rn
FROM TableA
)
SELECT top 5 ID, Name, NewId() [NewId]
FROM group
WHERE rn = 1
ORDER BY [newid]
I want to give row number only to the combination when it appears in a consecutive manner like ,
Please guide on how to get this type of sequence numbering in Tsql
I have tried with
ROW_NUMBER() Over (Partition by name,Order_type Order by REC_TS)
where record REC_TS is the time of order.
Name: Order type: Seq Number:
AAA ONLINE 1
AAA ONLINE 2
AAA STORE 1
AAA SPOT 1
AAA STORE 1
AAA SPOT 1
AAA SPOT 2
AAA ONLINE 1
Use ROW_NUMBER() with CTE. The query is based that when there are consecutive values, then different between ROW_NUMBER () OVER (ORDER BY REC_TS) and ROW_NUMBER () OVER (PARTITION BY Name, OrderType ORDER BY REC_TS) will remain same.
Something like this
DECLARE #Table1 TABLE
(
Name VARCHAR(10),
OrderType VARCHAR(10),
REC_TS DATETIME
)
Insert into #Table1
SELECT 'AAA','ONLINE','2014-09-01'
UNION ALL SELECT 'AAA','ONLINE','2014-09-02'
UNION ALL SELECT 'AAA','STORE','2014-09-03'
UNION ALL SELECT 'AAA','SPOT','2014-09-04'
UNION ALL SELECT 'AAA','STORE','2014-09-05'
UNION ALL SELECT 'AAA','SPOT','2014-09-06'
UNION ALL SELECT 'AAA','SPOT','2014-09-07'
UNION ALL SELECT 'AAA','ONLINE','2014-09-07'
;WITH CTE
AS (SELECT *,
ROW_NUMBER () OVER (ORDER BY REC_TS) - ROW_NUMBER () OVER (PARTITION BY Name,
OrderType
ORDER BY REC_TS) AS RowGroup
FROM #Table1)
SELECT ROW_NUMBER () OVER (PARTITION BY RowGroup,
Name,
OrderType
ORDER BY REC_TS) AS Sequence,
Name,OrderType
FROM CTE
ORDER BY REC_TS;
Try this:
CREATE TABLE Orders
(
Name VARCHAR(10),
OrderType VARCHAR(10),
REC_TS DATETIME
)
Insert into Orders
VALUES
('AAA','ONLINE','2014-09-01'),
('AAA','ONLINE','2014-09-02'),
('AAA','STORE','2014-09-03'),
('AAA','SPOT','2014-09-04'),
('AAA','STORE','2014-09-05'),
('AAA','SPOT','2014-09-06'),
('AAA','SPOT','2014-09-07'),
('AAA','ONLINE','2014-09-07')
;WITH OrdersRN
AS
(
SELECT [Name], OrderType, ROW_NUMBER() OVER (ORDER BY [REC_TS]) AS RN, [REC_TS]
FROM Orders
),
OrdersRecurs
AS
(
SELECT O1.Name, O1.OrderType, 1 As Seq, O1.RN
FROM OrdersRN O1
WHERE RN = 1
UNION ALL
SELECT O1.Name, O1.OrderType,
CASE
WHEN Prev.Name IS NULL THEN 1
WHEN Prev.Name = O1.Name AND Prev.OrderType = O1.OrderType THEN Prev.Seq + 1
ELSE 1
END As Seq,
O1.RN
FROM OrdersRN O1
INNER JOIN OrdersRecurs Prev
ON Prev.RN = O1.RN - 1
WHERE O1.RN <> 1
)
SELECT O.[Name], O.OrderType, O.[Seq]
FROM OrdersRecurs O
This should be a simple question, but I can't get it to work :(
How to select rows that have the maximum column value,as group by another column?
For example,
I have the following table definition:
ID
Del_Index
docgroupviewid
The issue now is that I want to group by results by docgroupviewid first, and then choose one row from each docgroupviewid group, depending on which one has the highest del_index.
I tried
SELECT docgroupviewid, max(del_index),id FROM table
group by docgroupviewid
But instead of return me with the correct id, it returns me with the earliest id from the group with the same docgroupviewid.
Any ideas?
I've struggled with this many times myself and the solution is to think about your query differently.
I want each DocGroupViewID row where the Del_Index is the highest(max) for all rows with that DocGroupViewID:
SELECT
T.DocGroupViewID,
T.Del_Index,
T.ID
FROM MyTable T
WHERE T.Del_Index = (
SELECT MAX( T1.Del_Index ) FROM MyTable T1
WHERE T1.DocGroupViewID = T.DocGroupViewID
)
It gets more complex when more than one row can have the same Del_Index, since then you need some way to choose which one to show.
EDIT: wanted to follow up with another option
You can use the RANK() or ROW_NUMBER() functions with a CTE to get more control over the results, as follows:
-- fake a source table
DECLARE #t TABLE (
ID int IDENTITY(1,1) PRIMARY KEY,
Del_Index int,
DocGroupViewID int
)
INSERT INTO #t
SELECT 1, 1 UNION ALL
SELECT 2, 1 UNION ALL
SELECT 3, 1 UNION ALL
SELECT 1, 2 UNION ALL
SELECT 2, 2 UNION ALL
SELECT 2, 2 UNION ALL
SELECT 1, 3 UNION ALL
SELECT 2, 3 UNION ALL
SELECT 3, 3 UNION ALL
SELECT 4, 3
-- show our source
SELECT * FROM #t
-- select using RANK (can have duplicates)
;WITH cteRank AS
(
SELECT
DocGroupViewID,
Del_Index,
ID,
RANK() OVER
(PARTITION BY DocGroupViewID ORDER BY Del_Index DESC)
AS RowRank,
ROW_NUMBER() OVER
(PARTITION BY DocGroupViewID ORDER BY Del_Index DESC)
AS RowNumber
FROM #t
)
SELECT *
FROM cteRank
WHERE RowRank = 1
-- select using ROW_NUMBER
;WITH cteRowNumber AS
(
SELECT
DocGroupViewID,
Del_Index,
ID,
RANK() OVER
(PARTITION BY DocGroupViewID ORDER BY Del_Index DESC)
AS RowRank,
ROW_NUMBER() OVER
(PARTITION BY DocGroupViewID ORDER BY Del_Index DESC)
AS RowNumber
FROM #t
)
SELECT *
FROM cteRowNumber
WHERE RowNumber = 1
If you have ways to sort out ties, just add it to the ORDER BY.
You will have to complicate your query a little bit:
select a.docgroupviewid, a.del_index, a.id from table a
where a.del_index = (select max(b.del_index) from table
where b.docgroupviewid = a.docgroupviewid)