SQL - Rank function - sql-server

I am trying to rank data based off multiple factors and having trouble doing so.
I want to rank each Batch and Material based off the most recent entry date and max value material doc item. (So 2 over 1 etc)
In the above sample data I would expect row 5 to be ranked 1 as it is the most recent date with the highest material doc item.
Current Logic:
RANK () OVER (PARTITION BY BATCH, MATERIAL ORDER BY BATCH, MATERIAL , ENTRY_DATE , MATERIAL_DOC_ITEM DESC ) AS RANK_NUM
Any guidance would be much appreciated

You need DESC after the ENTRY_DATE as well to get most recent date. Also note no need to include batch and material in the order by as the ordering is within the partition
RANK () OVER (PARTITION BY BATCH, MATERIAL ORDER BY ENTRY_DATE DESC, MATERIAL_DOC_ITEM DESC ) AS RANK_NUM

Related

SQL Delete Rows with Duplicate Key Keeping Most Recent

Dearest Professionals,
I have a table that sometimes has rows created with duplicate Invoice #'s (EMP_ID). In these rows, there separate date (FILE_DATE) and time (FILE_TIME) columns (genius database design there). I need to remove the older rows of any duplicated EMP_ID's in this database, keeping the most recent date (from FILE_DATE) + time (from FILE_TIME).
Both FILE_DATE and FILE_TIME are date/time field in the database. The software we use writes to this table, adding the date of the invoice to the FILE_DATE column, with YYYY-MM-DD 00:00:00.000 (the zeros all hard coded). Then the FILE_TIME field has 1900-01-01 HH:mm:ss.SSS, the 1900-01-01 hard coded. (the time stamp comes from the time the row was written to the database)
So, long story short, I need to marry these two together, to get the DATE portion of FILE_DATE and the time portion of FILE_TIME, to get the most recent (IF duplicates exist of EMP_ID) and delete all duplicated that are not the most recent of the married FILE_DATE & FILE_TIME.
Here is a sample of what a Before & After situation would look like.
BEFORE:
AFTER:
Any and all help would be insanely appreciated.
Using some good old CTE "magic":
WITH CTE AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY EMP_ID
ORDER BY FILE_DATE DESC, FILE_TIME DESC) AS RN
FROM YourTable)
DELETE FROM CTE
WHERE RN > 1;
I think this can be accomplished using MAX and GROUP BY:
select B.EMP_ID
, B.File_date
, Max(B.File_Time) as MaxFileTime
, B.DESC_TEXT_1
from Before B
group
by B.EMP_ID
, B.File_date
, B.DESC_TEXT_1

t sql sort by calculated column

I'm on T-SQL 2014 and try to order products by their price. Now here is the problem: the price is a calculated field. Eg. I have created a function which evaluates a number of pricing rules (maybe about 4 tables with each about 4,000,000 records combined with JOINs to fit to the current login) and returns the users price for the product. While this is OK if I just want to return the price for a limited number of products it is way to slow if I want to sort by this.
I was thinking about having an additional table like UserProductPrice which will get calculated in the background but this will obviously not always have the correct price in it as the rules etc. could change in between the calculation.
Any suggestion on how I could sort by the price would be most appreciated.
You could use the ROW_NUMBER() function and place this into a temp table:
SELECT
Product,
dbo.ufnPrice(Price) as Price,
ROW_NUMBER() OVER (PARTITION BY Product ORDER BY dbo.ufnPrice(Price) DESC) AS Ranking
INTO #Products
FROM dbo.Products
SELECT
Product,
Price,
FROM #Products
WHERE Ranking = 1
DROP TABLE #Products
Should give you what you need.

SQL Get Second Record

I am looking to retrieve only the second (duplicate) record from a data set. For example in the following picture:
Inside the UnitID column there is two separate records for 105. I only want the returned data set to return the second 105 record. Additionally, I want this query to return the second record for all duplicates, not just 105.
I have tried everything I can think of, albeit I am not that experience, and I cannot figure it out. Any help would be greatly appreciated.
You need to use GROUP BY for this.
Here's an example: (I can't read your first column name, so I'm calling it JobUnitK
SELECT MAX(JobUnitK), Unit
FROM JobUnits
WHERE DispatchDate = 'oct 4, 2015'
GROUP BY Unit
HAVING COUNT(*) > 1
I'm assuming JobUnitK is your ordering/id field. If it's not, just replace MAX(JobUnitK) with MAX(FieldIOrderWith).
Use RANK function. Rank the rows OVER PARTITION BY UnitId and pick the rows with rank 2 .
For reference -
https://msdn.microsoft.com/en-IN/library/ms176102.aspx
Assuming SQL Server 2005 and up, you can use the Row_Number windowing function:
WITH DupeCalc AS (
SELECT
DupID = Row_Number() OVER (PARTITION BY UnitID, ORDER BY JobUnitKeyID),
*
FROM JobUnits
WHERE DispatchDate = '20151004'
ORDER BY UnitID Desc
)
SELECT *
FROM DupeCalc
WHERE DupID >= 2
;
This is better than a solution that uses Max(JobUnitKeyID) for multiple reasons:
There could be more than one duplicate, in which case using Min(JobUnitKeyID) in conjunction with UnitID to join back on the UnitID where the JobUnitKeyID <> MinJobUnitKeyID` is required.
Except, using Min or Max requires you to join back to the same data (which will be inherently slower).
If the ordering key you use turns out to be non-unique, you won't be able to pull the right number of rows with either one.
If the ordering key consists of multiple columns, the query using Min or Max explodes in complexity.

Compute sum for distinct order numbers in ssrs report

I'm using a SQL Server 2008R2 Database and SSRS Report Builder 3.0
Trying to compute the sum of the amount owed for each order id (need to show the itemids)...but when I do, the amount owed is showing 400 (instead of 200 - line 4, 100 instead of 50 in line 7, line 9 is correct. As a result the Total line is way off)
=Sum(Fields!owe.Value)
The report is grouped by the campus.
I understand that ssrs is probably not the best place to do this computation but I don't know how to do outside of ssrs....I tried distinct and group by so far with no results.
Below is how I need the report to show like....
Thanks in advance.
Incorrect amounts are
Another example as it should display the subtotals
I would modify the SQL to produce an extra column just for purposes of summing the Owe on an OrderId. Use the Row Number to get the first item in each order, and only supply the Owe value for that item for each order:
WITH cte AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY OrderId ORDER BY ItemId) AS rn
FROM MyTable
WHERE (whatever filters you use)
)
SELECT *,
CASE WHEN rn=1 THEN Owe ELSE 0 END AS OrderOwe
FROM cte
ORDER BY Campus, CustomerId, OrderId, ItemId
Then simply change the expression for the "Owe" textbox in your SubTotal row to this:
=Sum(Fields!OrderOwe.Value)
And you will get the sum of the Owe per order instead of per item.
Well if your owe is always the same for each item in the group you could add a Sum/Count of the item in the group which would give you the correct results in all the cases above.

FInding max value from TOP selection grouped by key in SQL Server

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

Resources