Я пытаюсь очистить некоторые адреса. У меня есть таблица, в которой есть город, штат, индекс в одной строке, и я пытаюсь их разобрать. Я создал функцию с табличным значением, потому что, насколько я понимаю, она быстрее.
Таблица customerAddress немного шаткая, в ней есть записи для каждой строки адреса. Таким образом, customer_id может содержать от 2 до 4 записей. My WHERE ищет последние 4 числа c, и в нем есть, а в первой строке никогда не должно быть города, штата, почтового индекса.
Вот как выглядит таблица customerAddress:
customer_id address_line_id address_data
10447 3 CULVER CITY, CA 90233-6011
10893 3 VIRGINIA BEACH, VA 23452
10461 3 DOWNERS GROVE, IL 60515
10894 1 1111 BOHM DRIVE
10894 2 PO BOX 109
10894 3 LITTLE CHUTE, WI 54140-0109
10895 1 1990 WEST 32ND AVE.
10895 2 DENVER, CO 80211
Итак, вот мой запрос:
SELECT customer_id, address_line_id, address_data, oa.*
INTO #tmpAddress
FROM customerAddress
OUTER APPLY
( SELECT * FROM [dbo].[parseCityStateZip](customerAddress.address_data) ) oa
WHERE
address_data LIKE '%,%' AND
ISNUMERIC( RIGHT(address_data,4) ) = 1 AND
address_line_id != 1
ORDER BY customer_id, address_line_id
Вот план выполнения запроса. Если я читаю правильно (что, вероятно, не так), функция с табличным значением выполнялась за 9 минут 33 секунды, но фильтр был 123% ?? https://www.brentozar.com/pastetheplan/?id=S13IITvZw
Я использовал OUTER APPLY
, потому что думал, что это лучше, чем вызывать функцию для каждого поля, и нет ничего, что я мог бы присоединить к нему для LEFT JOIN
.
Вот моя табличная функция, которую я вызываю в OUTER APPLY
ALTER FUNCTION [dbo].[parseCityStateZip] (@inStr varchar(255) )
RETURNS @returnTable
TABLE (
[city] varchar(255),
[state] varchar(255),
[zip] varchar(12),
[country] varchar(50) NULL,
[intlFlag] bit NOT NULL DEFAULT(0))
AS
BEGIN
DECLARE
@newStr varchar(255), @strCity varchar(255), @strState varchar(255), @strZip varchar(12), @strCountry varchar(255),
@strIntlFlag bit
-- Determines if Zip Code is 5 or 9 Digits
-- Stores to variable and chops it off saving the remainign to @newStr
IF CHARINDEX('-', @inStr, 0) > 0
BEGIN
SELECT @strZip = RIGHT(@inStr, 10)
SELECT @newStr = TRIM(SUBSTRING(@inStr, 0, LEN(@inStr) - 9))
END
ELSE
BEGIN
SELECT @strZip = RIGHT(@inStr, 5)
SELECT @newStr = TRIM(SUBSTRING(@inStr, 0, LEN(@inStr) - 4))
END
-- Looks for the , separating City, State
-- Saves everything before the , and City, and after as State
-- Use TRIM to remove extra spaces before or after the State
SELECT @strCity = TRIM( SUBSTRING( @newStr, 0, CHARINDEX(',', @newStr, 0) ) )
SELECT @strState = ULTRA.dbo.RemoveNonAlphaCharacters( TRIM( SUBSTRING( @newStr, CHARINDEX(',', @newStr, 0) + 1, LEN(@newStr) - CHARINDEX(',', @newStr, 0) ) ) )
-- Checks to see if the State matches a state in the info table, and is in the United States
IF EXISTS( SELECT * FROM [ULTRA].[dbo].[CityStateInfo] WHERE [Country] = 'United States' AND ([State_long] = @strState OR [State_abbr] = @strState))
SELECT @strCountry = 'United States', @strIntlFlag = 0
ELSE
SELECT @strCountry = 'INTERNATIONAL', @strIntlFlag = 1
INSERT INTO @returnTable VALUES (@strCity, @strState, @strZip, @strCountry, @strIntlFlag)
RETURN
END
И вот план выполнения для хорошей меры: https://www.brentozar.com/pastetheplan/?id=BkFCQawZP
Есть ли способ вывести все поля в запросе, например:
SELECT
customer_id,
address_data,
(SELECT * FROM [parseCityStateZip](address_data))
FROM customerAddress
Ускорит ли это запрос? Если нет, что можно сделать, чтобы ускорить его?
Я использую последний SQL сервер и SSMS