Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
与SQL Where筛选器斗争_Sql_Sql Server - Fatal编程技术网

与SQL Where筛选器斗争

与SQL Where筛选器斗争,sql,sql-server,Sql,Sql Server,我有一个表,[Customer],其中有[postcode]和[totalValue]字段 我需要设计一个查询,返回所有[postcode]的前两个字符,然后返回该特定邮政编码组的[totalValue]的总和(因此NW、L1等各有一个值) 我有以下代码,运行良好: SELECT LEFT(postcode, 2), SUM(totalValue) FROM Customer GROUP BY LEFT(postcode, 2) …但是我在[Customer]中的条目不包含有效的[po

我有一个表,[Customer],其中有[postcode]和[totalValue]字段

我需要设计一个查询,返回所有[postcode]的前两个字符,然后返回该特定邮政编码组的[totalValue]的总和(因此NW、L1等各有一个值)

我有以下代码,运行良好:

SELECT LEFT(postcode, 2), SUM(totalValue)
  FROM Customer
  GROUP BY LEFT(postcode, 2)
…但是我在[Customer]中的条目不包含有效的[postcode]

有效的英国邮政编码始终是一个或两个字母后跟一个数字(例如LE1、L12等)


我想将所有不正确的/空的/空的[邮政编码]记录过滤到一个单独的记录条目中,但这超出了我的技能范围。

您可以像使用
一样使用

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);
这是选择:

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
试试这个

SELECT LEFT(postcode, 2), SUM(totalValue)
  FROM Customer
WHERE ISNUMERIC(LEFT(postcode, 1))<> 1
GROUP BY LEFT(postcode, 2)
选择左侧(邮政编码,2),总和(总值)
来自客户
其中ISNUMERIC(左(邮政编码,1))1
按左分组(邮政编码,2)
希望这有帮助。

试试这个。所有不正确(或空)的邮政编码将累加在“--”条目中:

查询:


使用
CTE
收集数据。无效邮政编码将被分组为“无效”。

您对有效邮政编码的假设有点错误

有效的英国邮政编码始终是一个或两个字母后跟一个数字(例如LE1、L12等)

最简单的说法是:

您可以为以下各项定义模式匹配:

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)中的一个。维基百科上的指导原则规定:

  • 只有一位数地区的地区:BR、FY、HA、HD、HG、HR、HS、HX、JE、LD、SM、SR、WC、WN、ZE(尽管WC总是由一个更进一步的字母细分,例如WC1A)
  • 只有两位数地区的地区:AB、LL、SO
  • 地区为“0”(零)的区域:BL、BS、CM、CR、FY、HA、PR、SL、SS(BS是唯一同时具有地区0和地区10的区域)
  • 通过在数字后和空格前插入一个字母,进一步划分了以下伦敦市中心的单位数区域:EC1–EC4(但不是EC50)、SW1、W1、WC1、WC2和E1部分(E1W)、N1(N1C和N1P)、NW1(NW1W)和SE1(SE1P)
  • 字母QVX不用于第一个位置
  • 字母IJZ不用于第二个位置
  • 当结构以A9A开头时,出现在第三个位置的唯一字母是ABCDEFGHJKPSTUW
  • 当结构以AA9A开头时,出现在第四个位置的唯一字母是abehmnpvwxy
  • 最后两个字母不使用字母CIKMOV,以免手写时与数字或其他字母相似
  • 邮政编码区是十位数字中的一位:0到9,0仅在邮政镇使用9后使用,Croydon和Newport除外(见上文)

由于SQL Server不支持完整的正则表达式,所以解释所有这些警告会变得有点复杂。如果您真的想要傻瓜式验证,我倾向于使用来自的正则表达式,并使用CLR函数验证邮政编码。

OP表示他们也希望显示无效代码,这是一个单独的条目。。。这只是删除了它们。只需跳出框来思考,但第二个查询不会对数据进行聚合,因为邮件可能会丢失<代码>其中邮政编码**与“[A-Z][A-Z0-9][0-9]”不同,但可以在单个查询中完成此操作。。。只是想跳出框框。@Mascaro先生。只是没有正确地分析整个句子。它以“我想过滤掉…”开头。我想过滤掉所有不正确的/空的/空的[postcode]记录到一个单独的记录条目中,但这超出了我的技能范围。“什么版本的SQL server?标量函数对性能很糟糕。”。这里真的没有任何理由使用它。你是对的,我在当前项目中编辑了一些用于其他目的的代码,但没有真正检查其他解决方案,这是我的错
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;