我有一个表[Customer],它有[postcode]和[totalValue]字段。
我需要设计一个查询,它返回所有[postcode]的前两个字符,然后是该特定邮政编码组的[totalValue]的SUM(因此NW,L1等各有一个值)。< / p>
我有这个代码,运行正常:
SELECT LEFT(postcode, 2), SUM(totalValue)
FROM Customer
GROUP BY LEFT(postcode, 2)
...但是,[客户]中的条目不包含有效的[邮政编码]。
有效的英国邮政编码总是一个或两个字母后跟一个数字(例如LE1,L12等)。
我想将所有不正确/空/ Null [邮政编码]记录过滤到单独的记录条目中,但这超出了我的技能。
答案 0 :(得分:5)
您可以使用LIKE
:
where postcode like '[A-Z][A-Z0-9][0-9]%'
您可能还想检查长度和其他特征,但这可以回答您的具体问题。
编辑:
要获得单独的条目,请使用case
:
SELECT (CASE WHEN postcode like '[A-Z][A-Z0-9][0-9]%'
THEN LEFT(postcode, 2)
ELSE 'Separate Entry'
END) as PostCode2, SUM(totalValue)
FROM Customer
GROUP BY (CASE WHEN postcode like '[A-Z][A-Z0-9][0-9]%'
THEN LEFT(postcode, 2)
ELSE 'Separate Entry'
END);
答案 1 :(得分:1)
您对有效邮政编码的假设略有不足
有效的英国邮政编码总是一个或两个字母后跟一个数字(例如LE1,L12等)。
最简单的说法是valid formats for a UK Postcode:
+----------+---------------------------------------------+----------+
| Format | Coverage | Example |
+----------+---------------------------------------------+----------+
| AA9A 9AA | WC postcode area; EC1–EC4, NW1W, SE1P, SW1 | EC1A 1BB |
+----------+---------------------------------------------+----------+
| A9A 9AA | E1W, N1C, N1P | W1A 0AX |
+----------+---------------------------------------------+----------+
| A9 9AA | B, E, G, L, M, N, S, W | M1 1AE |
| A99 9AA | | B33 8TH |
+----------+---------------------------------------------+----------+
| AA9 9AA | All other postcodes | CR2 6XH |
| AA99 9AA | | DN55 1PT |
+----------+---------------------------------------------+----------+
您可以为每个模式匹配:
AA9A 9AA - [A-Z][A-Z][0-9][A-Z] [0-9][A-Z][A-Z]
A9A 9AA - [A-Z][0-9][A-Z] [0-9][A-Z][A-Z]
A9 9AA - [A-Z][0-9] [0-9][A-Z][A-Z]
A99 9AA - [A-Z][0-9][0-9] [0-9][A-Z][A-Z]
AA9 9AA - [A-Z][A-Z][0-9] [0-9][A-Z][A-Z]
AA99 9AA - [A-Z][A-Z][0-9][0-9] [0-9][A-Z][A-Z]
对于可重复使用的东西,我认为值得存储,所以我会为它创建一个表:
CREATE TABLE dbo.SimplePostCodeValidation
(
PostCode VARCHAR(8) NOT NULL,
Pattern VARCHAR(50) NOT NULL
);
INSERT dbo.SimplePostCodeValidation (PostCode, Pattern)
VALUES
('AA9A 9AA', '[A-Z][A-Z][0-9][A-Z] [0-9][A-Z][A-Z]'),
('A9A 9AA', '[A-Z][0-9][A-Z] [0-9][A-Z][A-Z]'),
('A9 9AA', '[A-Z][0-9] [0-9][A-Z][A-Z]'),
('A99 9AA', '[A-Z][0-9][0-9] [0-9][A-Z][A-Z]'),
('AA9 9AA', '[A-Z][A-Z][0-9] [0-9][A-Z][A-Z]'),
('AA99 9AA', '[A-Z][A-Z][0-9][0-9][0-9][A-Z][A-Z]'),
-- REPEAT THE POSTCODES WITHOUT SPACES
('AA9A9AA', '[A-Z][A-Z][0-9][A-Z][0-9][A-Z][A-Z]'),
('A9A9AA', '[A-Z][0-9][A-Z][0-9][A-Z][A-Z]'),
('A99AA', '[A-Z][0-9][0-9][A-Z][A-Z]'),
('A999AA', '[A-Z][0-9][0-9][0-9][A-Z][A-Z]'),
('AA99AA', '[A-Z][A-Z][0-9][0-9][A-Z][A-Z]'),
('AA999AA', '[A-Z][A-Z][0-9][0-9][0-9][A-Z][A-Z]');
现在您可以轻松验证您的邮政编码:
DECLARE @T TABLE (Postcode VARCHAR(8));
INSERT @T (PostCode)
SELECT PostCode
FROM dbo.SimplePostCodeValidation
UNION ALL
SELECT PostCode
FROM (VALUES ('123456'), (''), ('TEST')) t (PostCode);
SELECT t.PostCode, IsValid = CASE WHEN pc.PostCode IS NULL THEN 0 ELSE 1 END
FROM @T AS t
LEFT JOIN SimplePostCodeValidation AS pc
ON t.PostCode LIKE pc.Pattern;
返回:
PostCode IsValid
----------------------
AA9A 9AA 1
A9A 9AA 1
A9 9AA 1
A99 9AA 1
AA9 9AA 1
AA99 9AA 1
123456 0
0
TEST 0
要将此应用于您的情况,您可以使用:
SELECT CASE WHEN pc.PostCode IS NULL THEN 'Invalid' ELSE LEFT(c.postcode, 2) END,
TotalValue = SUM(totalValue)
FROM Customer AS c
LEFT JOIN SimplePostCodeValidation AS pc
ON t.PostCode LIKE pc.Pattern;
GROUP BY CASE WHEN pc.PostCode IS NULL THEN 'Invalid' ELSE LEFT(c.postcode, 2) END;
如果您想要变得更复杂,实际上有效的邮政编码存在进一步的限制,例如:如果是模式A9 9AA
则第一个字母只能是(B,E,G,L,M,N,S,W)中的一个。该指南载于维基百科州:
由于SQL Server不支持完整的正则表达式,因此考虑到所有这些警告会更加复杂。如果您真的想要进行傻瓜证明验证,我倾向于使用answers this question中的正则表达式,并使用CLR函数来验证邮政编码。
答案 2 :(得分:0)
试试这个。所有不正确(或NULL)的邮政编码都将在“ - ”条目中累积:
SELECT
CASE
WHEN postcode like '[A-Z][A-Z0-9][0-9]%'
THEN LEFT(postcode, 2)
ELSE '--'
END,
SUM(totalValue)
FROM Customer
GROUP BY
CASE
WHEN postcode like '[A-Z][A-Z0-9][0-9]%'
THEN LEFT(postcode, 2)
ELSE '--'
END
答案 3 :(得分:0)
查询:
border-collapse
使用WITH CTE AS (SELECT CASE WHEN postcode LIKE('[A-Z][A-Z0-9][0-9]%')
THEN LEFT(postcode,2) ELSE 'Invalid' END AS PostCode
,totalValue
FROM Customer)
SELECT PostCode, SUM(totalValue) as totalValue
FROM CTE
GROUP BY PostCode
收集数据。无效的邮政编码将被归为“无效”。
答案 4 :(得分:-1)
试试这个..
SELECT LEFT(postcode, 2), SUM(totalValue)
FROM Customer
WHERE ISNUMERIC(LEFT(postcode, 1))<> 1
GROUP BY LEFT(postcode, 2)
希望这有帮助。
答案 5 :(得分:-2)
这是选择:
SELECT LEFT(postcode, 2), SUM(totalValue)
FROM Customer
WHERE postcode IS NOT NULL AND postcode != '' AND dbo.fn_isValid(postcode) = 1
GROUP BY LEFT(postcode, 2)
UNION
SELECT 'NULL', SUM(totalValue)
FROM Customer
WHERE postcode IS NULL
GROUP BY LEFT(postcode, 2)
UNION
SELECT 'EMPTY', SUM(totalValue)
FROM Customer
WHERE postcode = ''
GROUP BY LEFT(postcode, 2)
UNION
SELECT 'WRONG', SUM(totalValue)
FROM Customer
WHERE dbo.fn_isValid(postcode) = 0
GROUP BY LEFT(postcode, 2)
然后你需要评估函数,如下所示:
CREATE FUNCTION [dbo].[fn_IsValid]
(
@Code nchar(32)
)
RETURNS bit
AS
BEGIN
DECLARE @Status bit
SET @Status = -- Your validation logic
--be aware of empty and null values
RETURN @Status
END