Suppose there're 2 tables with data like below:
-- Table #Detail
TelNO
----------
001xxxxx
020xxxxx
021xxxxx
800xxxxx
400xxxxx
28011111
82188888
22223333
...
...
-- Table #FeeRate
Expression Price Description
---------- ------- --------------------------------------------------
001% 10.00 International call
0[^0]% 5.00 National call
800% .00 Free call
400% .80 800 like, but caller need pay for local part
ELSE,How? .20 Others/Local call
I want to select data from the 2 tables JOINed on dbo.FUNCTION_Match (TelNO, Expression)
condition. (dbo.FUNCTION_Match
is a crude function i wroted to match TelNO
and Expression
. In this sample, you can treat it as TelNO LIKE Expression
).
So the SQL & query result is
SELECT * FROM #Detail d
LEFT JOIN #FeeRate f ON d.TelNO LIKE f.Expression
TelNO Expression Price Description
---------- ---------- ------- --------------------------------------------------
001xxxxx 001% 10.00 International call
020xxxxx 0[^0]% 5.00 National call
021xxxxx 0[^0]% 5.00 National call
800xxxxx 800% .00 Free call
400xxxxx 400% .80 800 like, but caller need pay for local part
28011111 NULL NULL NULL
82188888 NULL NULL NULL
22223333 NULL NULL NULL
The problem is clear, those local calls in #Detail can't matched Others
FeeRate.
My crude FUNCTION_Match function has handled multi-expressions like TelNO NOT LIKE '0%' AND TelNO NOT LIKE [84]00% OR TelNO LIKE '0755%'
to match Others
FeeRate, but it's hard to write a correct multi-expression to express ELSE
when there're many records in #FeeRate table.
So, is there a way to implement ELSE
expression from data ?
SQLs to create sample data
CREATE TABLE #Detail (TelNO VARCHAR(10) DEFAULT '')
CREATE TABLE #FeeRate (Expression VARCHAR(20) DEFAULT '', Price NUMERIC(10,2) DEFAULT 0, Description VARCHAR(50) DEFAULT '')
INSERT INTO #Detail VALUES ('001xxxxx')
INSERT INTO #Detail VALUES ('020xxxxx')
INSERT 开发者_运维技巧INTO #Detail VALUES ('021xxxxx')
INSERT INTO #Detail VALUES ('800xxxxx')
INSERT INTO #Detail VALUES ('400xxxxx')
INSERT INTO #Detail VALUES ('28011111')
INSERT INTO #Detail VALUES ('82188888')
INSERT INTO #Detail VALUES ('22223333')
INSERT INTO #FeeRate VALUES ('001%', 10.0, 'International call')
INSERT INTO #FeeRate VALUES ('0[^0]%', 5.0, 'National call')
INSERT INTO #FeeRate VALUES ('800%', 0.0, 'Free call')
INSERT INTO #FeeRate VALUES ('400%', 0.8, '800 like, but caller need pay for local part')
INSERT INTO #FeeRate VALUES ('ELSE,How?', 0.2, 'Others/Local call')
SELECT * FROM #Detail
SELECT * FROM #FeeRate
SELECT
*
FROM
#Detail d
LEFT JOIN #FeeRate f ON d.TelNO LIKE f.Expression
DROP TABLE #Detail
DROP TABLE #FeeRate
Add an extra column to your FeeRate
table, called Priority
. Assign higher priorities to the matches that should occur "earlier". Do two joins to the fee rate table, the second being a left join, and looking for a higher priority match. If the left join works, reject the result row:
CREATE TABLE #FeeRate (Expression VARCHAR(20) DEFAULT '', Price NUMERIC(10,2) DEFAULT 0, Description VARCHAR(50) DEFAULT '',Priority int)
INSERT INTO #FeeRate VALUES ('001%', 10.0, 'International call',5)
INSERT INTO #FeeRate VALUES ('0[^0]%', 5.0, 'National call',4)
INSERT INTO #FeeRate VALUES ('800%', 0.0, 'Free call',3)
INSERT INTO #FeeRate VALUES ('400%', 0.8, '800 like, but caller need pay for local part',2)
INSERT INTO #FeeRate VALUES ('%', 0.2, 'Others/Local call',1)
SELECT * FROM #Detail d
inner JOIN #FeeRate f ON d.TelNO LIKE f.Expression
left join #FeeRate f_anti on d.TelNo LIKE f_anti.Expression and f_anti.Priority > f.Priority
where
f_anti.Price is null
This probably allows you to simplify some of your other expressions also.
If there is only one "other" category, store its values in variables and substitute them in when there is no match using ISNULL
:
DECLARE @expression VARCHAR(20), @price NUMERIC (10,2), @description VARCHAR(50)
SELECT @expression = Expression, @price = Price, @description = [Description]
FROM #FeeRate
WHERE Expression = 'ELSE,How?'
SELECT d.TelNO, ISNULL(f.Expression, @expression) AS Expression,
ISNULL(f.Price, @price) AS Price,
ISNULL(f.[Description], @description) AS [Description]
FROM
#Detail d
LEFT JOIN #FeeRate f ON d.TelNO LIKE f.Expression
I don't know for sure what data you are having in #Detail table, but for the above data you can do something like this:
SELECT * FROM
#Detail d
LEFT JOIN #FeeRate f ON
(CASE
WHEN d.TelNO LIKE '%xxxxx' THEN TelNO
ELSE 'ELSE,How?'
END) LIKE f.Expression
精彩评论