August 30, 2022 at 3:49 pm
Hello everyone,
I am trying to understand how to build a logic in SQL which will create a field "ACTUAL_SHIPPER_CODE_LOAD" that will be populating the value of S1SCDA field but only the first row of it.
Like in this example, all fields for this MBOL_JN should equal to 15 because it is the first row appearing.
I believe in SQL it should be some kind of logic that will look at the first row taking into consideration the 1st row of MBOL_JN and the min value of LD_JN.
I have filtered down to only one BOL but obviously there will be many more so it should look 1) new MBOL_JN appearing and then 2) first min value of LD_JN.
Any ideas how it can be done?
SELECT distinct REPLACE(MASTER_BOL_NUMBER_WK_DC, ' ', '') AS 'MBOL_JN',
LTRIM(RTRIM(AR_LOAD_WK_DC)) AS 'LD_JN',
S1SCDA,
ACT_SHIPPER_NAME
FROM WF_AR_MBOL
WHERE SORT_ORDER=1
GROUP BY MASTER_BOL_NUMBER_WK_DC, AR_LOAD_WK_DC, S1SCDA, ACT_SHIPPER_NAME, MASTER_BOL_NUMBER
August 30, 2022 at 6:30 pm
If you are hoping for a coded solution, please provide some sample data in the form of consumable CREATE TABLE and INSERT statements, along with desired results based on that sample data.
The absence of evidence is not evidence of absence
- Martin Rees
The absence of consumable DDL, sample data and desired results is, however, evidence of the absence of my response
- Phil Parkin
August 31, 2022 at 2:51 am
@Phil Parkin I cannot provide such information. I don't know how and I am not sure I am allowed.
I managed to do something similar to what I need but it doesn't work completely correctly.
For some reason MIN window function () doesn't return the value that I need.
It should be all Old Dominion - Ogden for all of them.
SELECT distinct REPLACE(MASTER_BOL_NUMBER_WK_DC, ' ', '') AS 'MBOL_JN',
LTRIM(RTRIM(AR_LOAD_WK_DC)) AS 'LD_JN',
S1SCDA,
ACT_SHIPPER_NAME,
MIN(S1SCDA) OVER (PARTITION BY REPLACE(MASTER_BOL_NUMBER_WK_DC, ' ', '') ORDER BY LTRIM(RTRIM(AR_LOAD_WK_DC)) ) AS 'ACTUAL_SHIPPER_CODE_LOAD',
MIN(ACT_SHIPPER_NAME) OVER (PARTITION BY REPLACE(MASTER_BOL_NUMBER_WK_DC, ' ', '') ORDER BY LTRIM(RTRIM(AR_LOAD_WK_DC)) ) AS 'ACTUAL_SHIPPER_LOAD'
FROM WF_AR_MBOL
WHERE SORT_ORDER=1
GROUP BY MASTER_BOL_NUMBER_WK_DC, AR_LOAD_WK_DC, S1SCDA, ACT_SHIPPER_NAME, MASTER_BOL_NUMBER
August 31, 2022 at 7:26 am
Please read this article for details showing how to post sample data.
The absence of evidence is not evidence of absence
- Martin Rees
The absence of consumable DDL, sample data and desired results is, however, evidence of the absence of my response
- Phil Parkin
August 31, 2022 at 8:48 am
As Phil said, provide an easy digestable testcase. So it can run on a test system to reproduce the solution. You've already shared a screenshot
You can mock the tablenames/values as long this issue crops up.
August 31, 2022 at 3:17 pm
I think you are probably looking for RANK() OVER(PARTITION BY MBOL_LN ORDER BY LD_JN) AS [SEQ_NO]
This will give you a sequential RANK value which resets each time MOBL_LN changes. If you set this up in a CTE you can then filter by SEQ_NO = 1. This gives you the FIRST line for each MOBL_LN. If you then need to get MIN(S1SCDA) you can do that separately.
Break the problen down into its component parts using CTEs and then put all the CTEs together. most of the time the query engine will still produce a close-to-optimal plan, it just makes it easier to test and read.
August 31, 2022 at 10:17 pm
I think you need the value from the row with the min AR_LOAD_WK_DC, not the min values of the shipper code and name. If you change your code to use FIRST_VALUE instead of MIN, you may get what you need. If trimming the columns and replacing spaces doesn't change the order or uniqueness, then you don't need to do it in the windowed functions.
FIRST_VALUE(S1SCDA) OVER (PARTITION BY MASTER_BOL_NUMBER_WK_DC ORDER BY AR_LOAD_WK_DC) AS ACTUAL_SHIPPER_CODE_LOAD
As you need multiple columns from the first row, I would probably join to a row_number query, rather than use two window functions. Rank would also work in this case, and if you like cte's you can put the row_number query in a cte. I assume you need the sort_order filter as it was in your original query.
SELECT REPLACE(a.MASTER_BOL_NUMBER_WK_DC, ' ', '') AS 'MBOL_JN',
LTRIM(RTRIM(a.AR_LOAD_WK_DC)) AS 'LD_JN',
a.S1SCDA,
a.ACT_SHIPPER_NAME,
b.S1SCDA AS ACTUAL_SHIPPER_CODE_LOAD,
b.ACT_SHIPPER_NAME AS ACTUAL_SHIPPER_LOAD,
FROM WF_AR_MBOL AS a
JOIN ( SELECT MASTER_BOL_NUMBER_WK_DC, S1SCDA, ACT_SHIPPER_NAME,
ROW_NUMBER() OVER (PARTITION BY MASTER_BOL_NUMBER_WK_DC
ORDER BY AR_LOAD_WK_DC) AS rn
FROM WF_AR_MBOL
WHERE SORT_ORDER=1
) AS b ON a.MASTER_BOL_NUMBER_WK_DC = b.MASTER_BOL_NUMBER_WK_DC
AND b.rn = 1
WHERE a.SORT_ORDER = 1
September 1, 2022 at 8:26 am
Ive been writing t-SQL code for 25 years and NEVER come across FIRST_VALUE, LAST_VALUE. I have always written a RANK() OVER() or a MIN() OVER() in a CTE and then joined back to to the CTE record. You just made future code MUCH easier to read,
#AlwaysLearning
September 1, 2022 at 2:59 pm
Ive been writing t-SQL code for 25 years and NEVER come across FIRST_VALUE, LAST_VALUE. I have always written a RANK() OVER() or a MIN() OVER() in a CTE and then joined back to to the CTE record. You just made future code MUCH easier to read,
#AlwaysLearning
You have to be careful with LAST_VALUE()
. The default window for both FIRST_VALUE()
and LAST_VALUE()
is ROWS UNBOUNDED PRECEDING
. This is fine for FIRST_VALUE()
, but returns the current row's value for LAST_VALUE()
, which is generally not what is expected.
Drew
J. Drew Allen
Business Intelligence Analyst
Philadelphia, PA
Viewing 9 posts - 1 through 8 (of 8 total)
You must be logged in to reply to this topic. Login to reply