I have the following table:
CREATE TABLE [dbo].[CASES]
(
[CASE_ID] INT NOT NULL,
[CASE_SECTION] INT NOT NULL,
[CASE_DATA] NVARCHAR(MAX) NOT NULL,
)
I want CASE_SECTION to increment based on whether the CASE_ID has changed.
Example:
CASE_ID CASE_SECTION CASE_DATA
---------------------------------------------
1 1 'FROG ATE THE FLY'
1 2 'FROG SAT ON LOG'
2 1 'CHEETAH CHEATAXED'
3 1 'BLUE CHEESE STINKS'
Basically, I want to do something similar to using ROW_NUMBER() OVER(PARTITION BY CASE_ID) as the CASE_DATA is inserted into the table.
Is there a way I can set the table up so that CASE_SECTION increments like this by default when data is inserted?
you can use rownumber:
Select row_number() over(partition by case_id order by case_data) as case_section, * from yourtable
If you can add either an IDENTITY or InsertedDateTime column to the table, you can use that to make Case_Section a computed column that uses row_number() partitioned by case_id.
Another poster suggested this, but if you order by case_data or any other column that isn't guaranteed to be ordinal, you run the risk that the value will move around as data is inserted and changes the order of the rows.
If your computation does row_number() over(partition by case_id order by [ColumnThatIncreasesWithEachInsert]) then the values will be stable over time.
Related
I am using a stored procedure in SQL Server 2014 to get the position of an item.
I've read about ROW_NUMBER but I am not sure how to use it (or if I can use it at all).
I have a table containing elements with IDs and dates and I would like to know the position of an element given its ID in the table sorted by date.
Let's say for instance I have these 5 items (ID. Date) :
ID DATE
1 2016-01-04
2 2016-01-05
3 2016-01-01
4 2016-01-02
5 2016-01-03
Using my stored procedure to get the position of 3., I want it to return 5 (the actual position of 3. when the table is ordered by date desc).
Thanks !
Yes, you can use ROW_NUMBER if you want only one result if there are duplicates, or RANK if you want every row that fits with your criteria (for instance, if there is more than 1 row with 2016-01-03 value):
;WITH CTE AS
(
SELECT *, RN = ROW_NUMBER() OVER(ORDER BY [Date] DESC)
FROM dbo.YourTable
)
SELECT ID, [Date]
FROM CTE
WHERE RN = 3;
I have data that returns the same value multiple times in one column, I only want to include the first value or even average the group, since they are all the same value. The group itself might have 3 rows of payments, but the payments are the same. I just want the three rows to show, but only the one payment in its own column.
In the data below I would like to add another column that averages Rich and Bob's value and inputs the amount in the top row for Rich and Bob.
Sample Data:
1 Rich 300
2 Rich 300
3 Rich 300
4 Bob 250
5 Bob 250
You probably want something like this:
Just paste this into an empty query window and exectue. Adapt to your needs...
DECLARE #tbl TABLE(ID INT, PersonName VARCHAR(100),Amount DECIMAL(6,2))
INSERT INTO #tbl VALUES
(1,'Rich',300)
,(2,'Rich',300)
,(3,'Rich',300)
,(4,'Bob',250)
,(5,'Bob',250);
WITH NumberedPerson AS
(
SELECT tbl.*
,ROW_NUMBER() OVER(PARTITION BY PersonName ORDER BY ID) PersonID
,AVG(Amount) OVER(PARTITION BY PersonName) PersonAvg
FROM #tbl AS tbl
)
SELECT *
,CASE WHEN PersonID=1 THEN PersonAvg ELSE NULL END AS AverageInFirstRow
FROM NumberedPerson
ORDER BY ID
But - to be honest - that is absolutely not the way how this should be done...
I have a table logging a floating point value from a scale (a weight). I'd like to evaluate the absolute value of the integral of this curve dynamically. I'm attempting to perform some simple algebra based on the trapezoidal approx. with a sampling rate (b-a=1) of one:
(b-a)((f(a)+f(b))/2 - f(a))
The values f(a) and f(b) represent the 2 most recent values logged in my SQL Server table. I've attempted the following with an evalution error:
SELECT TOP 2
SUM(Scale_Weight) OVER(ORDER BY t_stamp DESC)/2.0
FROM table
This query evaluates, but simply divides the most recent value by 2:
SELECT
SUM(Scale_Weight) OVER(ORDER BY t_stamp DESC)/2.0
FROM table
As you can see, I haven't even attempted the absolute value or the subtraction of the "2nd most recent" value because I didn't know how to reference a specific row (cell?). As a noob, I feel the math is doable in a single query, I just can't find the proper syntax. Thanks in advance.
So to update more clearly:
Thanks for the input ps2goat, though for some reason I'm unable to implement "TOP" function, so I currently have this:
SELECT ABS(SUM(Scale_Weight) OVER(PARTITION BY quality_code
ORDER BY t_stamp
ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)/2.0)
FROM table
Still need to subtract the preceding value, something like:
SELECT ABS(SUM(Scale_Weight) OVER(PARTITION BY quality_code
ORDER BY t_stamp
ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)/2.0
- 1 PRECEDING)
FROM table
Any ideas to reference the preceding value for subtraction?
You can use the LAG function to refer to the last value in a certain order. For example:
SELECT Scale_Weight AS Current, LAG(Scale_Weight) AS Last OVER (ORDER BY t_stamp)
FROM table
You can add your formula tothis query.
This is what I did. Instead of timestamps, I used an Identity field, as those are incremented and easier to enter manually (not sure if you had datetime values or actual timestamp values)
fiddle: http://sqlfiddle.com/#!6/77bcb/4/0
schema:
create table x(
xId int identity(1,1) not null primary key,
scale_weight decimal(12,4)
);
insert into x(scale_weight)
select 24.1234 union all
select 32.4455 union all
select 88.1234 union all
select 223.443;
The inner query (below) grabs the top two rows, ordered by id descending (use your t_stamp column). The outer query sums all the Scale_Weight values returned by the inner query and divides that value by two.
sql:
select SUM(Scale_Weight)/2.0 from
(
SELECT TOP 2 Scale_Weight
FROM x
ORDER BY xid DESC
) y
Apologies for goofy title. I am not sure how to describe the problem.
I have a table in SQL Server with this structure;
ID varchar(15)
ProdDate datetime
Value double
For each ID there can be hundreds of rows, each with its own ProdDate. ID and ProdDate form the unique key for the table.
What I need to do is find the maximum Value for each ID based upon the first 12 samples, ordered by ProdDate ascending.
Said another way. For each ID I need to find the 12 earliest dates for that ID (the sampling for each ID will start at different dates) and then find the maximum Value for those 12 samples.
Any idea of how to do this without multiple queries and temporary tables?
You can use a common table expression and ROW_NUMBER to logically define the TOP 12 per Id then MAX ... GROUP BY on that.
;WITH T
AS (SELECT *,
ROW_NUMBER() OVER (PARTITION BY Id ORDER BY ProdDate) AS RN
FROM YourTable)
SELECT Id,
MAX(Value) AS Value
FROM T
WHERE RN <= 12
GROUP BY Id
Two part question regarding partitioning in SQL.
In T-SQL when you use PARTITION BY is there a way to assign a unique number to each partition, in addition to something like row_number()?
E.g. row_number() would yield,
Action Timestamp RowNum
A '2013-1-10' 1
A '2013-1-11' 2
B '2013-1-12' 1
B '2013-1-13' 2
Whereas, in addition, uniquely identifying each partition could yield,
Action Timestamp RowNum PartitionNum
A '2013-1-10' 1 1
A '2013-1-11' 2 1
B '2013-1-12' 1 2
B '2013-1-13' 2 2
Then one could GROUP BY partition number.
Second part of my question is, how can you break out each partition and iterate through it, e.g.,
for each partition p
for each row r in p
do F(r)
Any way in T-SQL?
You could use dense_rank():
select *
, row_number() over (partition by Action order by Timestamp) as RowNum
, dense_rank() over (order by Action) as PartitionNum
from YourTable
Example at SQL Fiddle.
T-SQL is not good at iterating, but if you really have to, check out cursors.