I have a table containing rows of pricing.
Each row has 3 timestamps, insert_date, effective_from and effective_to. (example row below)
I have a query that will show me instances where rows where the price has been wrongly entered as zero.
What I'd like to be able to do, is know what the price field was BEFORE the last update (I didn't want these to be updated to zero)
The query I have now is:
SELECT *
FROM company..database_pricing_fixed
WHERE price = 0
AND status = 1
ORDER BY insert_date DESC
the table structure looks like this:
POSTCODE_KEY EXP_ID POSTCODE SOURCE_POSTCODE_DISTRICT DEST_POSTCODE_DISTRICT PRICE INSERT_DATE EFFECTIVE_FROM EFFECTIVE_TO ACCOUNT_ID STATUS
W11_TW6 3XA 75 TW6 3XA W11 NULL 0 24/12/2013 01:32 24/12/2013 01:31 24/12/2013 03:41 32523 1
With SQL Server 2012, you can use LEAD()
to get the second closest price if the latest one inserted is 0;
WITH cte AS (
SELECT POSTCODE_KEY, EXP_ID, POSTCODE, SOURCE_POSTCODE_DISTRICT,
DEST_POSTCODE_DISTRICT,
CASE WHEN PRICE = 0
THEN LEAD(PRICE) OVER (PARTITION BY POSTCODE_KEY
ORDER BY INSERT_DATE DESC)
ELSE PRICE
END PRICE,
INSERT_DATE, EFFECTIVE_FROM, EFFECTIVE_TO, ACCOUNT_ID,STATUS,
ROW_NUMBER() OVER (PARTITION BY POSTCODE_KEY ORDER BY INSERT_DATE DESC) rn
FROM DATABASE_pricing_fixed
)
SELECT * FROM cte WHERE rn=1
I modified the DDL in Joachim's SQL Fiddle a bit and utilized this structure to find a SQL Server 2008 solution.
A_PRICE and B_PRICE are the original PRICE columns in each table of the LEFT JOIN. CALCULATED_PRICE is the price you want to use and is the result of determining if table A.PRICE is 0 and falling back to B.PRICE if it is. It furthermore falls back to 0 if a.PRICE is 0 and there is no preceding insert to reference. You can get rid of A_PRICE and B_PRICE.
SEQ_A and SEQ_B are debugging values I used in my coding to help visualize the dataset. You can get rid of those.
Using this DDL:
CREATE TABLE DATABASE_pricing_fixed
([POSTCODE_KEY] varchar(11), [EXP_ID] int, [POSTCODE] varchar(7), [SOURCE_POSTCODE_DISTRICT] varchar(3), [DEST_POSTCODE_DISTRICT] varchar(4), [PRICE] int, [INSERT_DATE] varchar(16), [EFFECTIVE_FROM] varchar(16), [EFFECTIVE_TO] varchar(16), [ACCOUNT_ID] int, [STATUS] int)
;
INSERT INTO DATABASE_pricing_fixed
([POSTCODE_KEY], [EXP_ID], [POSTCODE], [SOURCE_POSTCODE_DISTRICT], [DEST_POSTCODE_DISTRICT], [PRICE], [INSERT_DATE], [EFFECTIVE_FROM], [EFFECTIVE_TO], [ACCOUNT_ID], [STATUS])
VALUES
('W11_TW6 3XA', 75, 'TW6 3XA', 'W11', NULL, 0, '24/12/2013 01:34', '24/12/2013 01:31', '24/12/2013 03:41', 32523, 1)
;
INSERT INTO DATABASE_pricing_fixed
([POSTCODE_KEY], [EXP_ID], [POSTCODE], [SOURCE_POSTCODE_DISTRICT], [DEST_POSTCODE_DISTRICT], [PRICE], [INSERT_DATE], [EFFECTIVE_FROM], [EFFECTIVE_TO], [ACCOUNT_ID], [STATUS])
VALUES
('W11_TW6 3XB', 75, 'TW6 3XA', 'W11', NULL, 47, '22/12/2013 01:32', '24/12/2013 01:31', '24/12/2013 03:41', 32523, 1)
;
INSERT INTO DATABASE_pricing_fixed
([POSTCODE_KEY], [EXP_ID], [POSTCODE], [SOURCE_POSTCODE_DISTRICT], [DEST_POSTCODE_DISTRICT], [PRICE], [INSERT_DATE], [EFFECTIVE_FROM], [EFFECTIVE_TO], [ACCOUNT_ID], [STATUS])
VALUES
('W11_TW6 3XC', 75, 'TW6 3XA', 'W11', NULL, 33, '24/12/2013 01:32', '24/12/2013 01:31', '24/12/2013 03:41', 32523, 1)
;
Solution:
WITH d1 AS (
SELECT
*
,Seq = ROW_NUMBER() OVER (PARTITION BY POSTCODE ORDER BY INSERT_DATE)
FROM DATABASE_pricing_fixed
)
SELECT a.POSTCODE_KEY
,a.EXP_ID
,a.POSTCODE
,a.SOURCE_POSTCODE_DISTRICT
,a.DEST_POSTCODE_DISTRICT
,A_PRICE = a.PRICE
,B_PRICE = b.PRICE
,CALCULATED_PRICE = COALESCE(NULLIF(a.PRICE, 0), b.PRICE, 0)
,a.INSERT_DATE
,a.EFFECTIVE_FROM
,a.EFFECTIVE_TO
,a.ACCOUNT_ID
,a.STATUS
,A_SEQ = a.Seq
,B_SEQ = b.Seq
FROM d1 a
LEFT JOIN d1 b
ON a.PRICE = 0
AND b.POSTCODE = a.POSTCODE
AND a.Seq - b.Seq = 1
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.