Sql server 在SQL pivot查询中使用默认值替换行中的空值

Sql server 在SQL pivot查询中使用默认值替换行中的空值,sql-server,Sql Server,使用SQL Server 2016数据库,我使用以下代码: SELECT * FROM ( SELECT u.firstname AS 'first name', u.lastname AS 'last name', gi.idnumber AS 'examcode', gg.finalgrade AS 'grade' FROM mdl_grade_grades gg INNER JOIN mdl_grade

使用SQL Server 2016数据库,我使用以下代码:

SELECT * FROM (
    SELECT
        u.firstname AS 'first name',
        u.lastname AS 'last name',
        gi.idnumber AS 'examcode',
        gg.finalgrade AS 'grade'
    FROM mdl_grade_grades gg
    INNER JOIN mdl_grade_items gi ON gg.itemid = gi.id
    INNER JOIN mdl_user u ON gg.userid = u.id
    WHERE gi.idnumber IN ('148','414','413','228','359','379','398','104','351','436','434','384','385','377','280','395')
    AND gg.userid = '62750'
) SOURCE
PIVOT (
    MAX(grade)
    FOR examcode IN ([148],[414],[413],[228],[359],[379],[398],[104],[351],[436],[434],[384],[385],[377],[280],[395])
) PIVT
ORDER BY 'last name', 'first name'
生成各种gi.examcodes分数的数据透视列表。 如果特定gi.examcode没有记录行,SQL Server数据库将返回NULL,如下所示:

first name  last name    148    413    228    359    379    398     104    351    436    434    384    385    377    280    395
John        Brown        94     96     97     NULL   NULL   NULL    100    NULL   NULL   94     86     83     85     93     NULL
first name  last name    148    413    228    359    379    398     104    351    436    434    384    385    377    280    395
John        Brown        94     96     97     None   None   None    100    None   None   94     86     83     85     93     None
当写入html页面时,该表显示空值,其中有空值。如何用泛型值替换返回的空值,如下所示:

first name  last name    148    413    228    359    379    398     104    351    436    434    384    385    377    280    395
John        Brown        94     96     97     NULL   NULL   NULL    100    NULL   NULL   94     86     83     85     93     NULL
first name  last name    148    413    228    359    379    398     104    351    436    434    384    385    377    280    395
John        Brown        94     96     97     None   None   None    100    None   None   94     86     83     85     93     None

您可以将当前查询设置为CTE或派生表,并使用ISNULL进行选择。

您可以将当前查询设置为CTE或派生表,并使用ISNULL进行选择。

不使用外部选择中的splat,而是寻址每个字段并处理null

SELECT 
    [first name]
    , [last name]
    , [examcode]
    ,isnull([148], 0) as [148]
    ,isnull([414], 0) as [414]
    ,isnull([413], 0) as [413]
    ,isnull([228], 0) as [228]
    ,isnull([359], 0) as [359]
    ,isnull([379], 0) as [379]
    ,isnull([398], 0) as [398]
    ,isnull([104], 0) as [104]
    ,isnull([351], 0) as [351]
    ,isnull([436], 0) as [436]
    ,isnull([434], 0) as [434]
    ,isnull([384], 0) as [384]
    ,isnull([385], 0) as [385]
    ,isnull([377], 0) as [377]
    ,isnull([280], 0) as [280]
    ,isnull([395], 0) as [395]
 FROM (
    SELECT
        u.firstname AS 'first name',
        u.lastname AS 'last name',
        gi.idnumber AS 'examcode',
        gg.finalgrade AS 'grade'
    FROM mdl_grade_grades gg
    INNER JOIN mdl_grade_items gi ON gg.itemid = gi.id
    INNER JOIN mdl_user u ON gg.userid = u.id
    WHERE gi.idnumber IN ('148','414','413','228','359','379','398','104','351','436','434','384','385','377','280','395')
    AND gg.userid = '62750'
) SOURCE
PIVOT (
    MAX(grade)
    FOR examcode IN ([148],[414],[413],[228],[359],[379],[398],[104],[351],[436],[434],[384],[385],[377],[280],[395])
) PIVT
ORDER BY 'last name', 'first name'

不要在外部select中使用splat,而是寻址每个字段并处理null

SELECT 
    [first name]
    , [last name]
    , [examcode]
    ,isnull([148], 0) as [148]
    ,isnull([414], 0) as [414]
    ,isnull([413], 0) as [413]
    ,isnull([228], 0) as [228]
    ,isnull([359], 0) as [359]
    ,isnull([379], 0) as [379]
    ,isnull([398], 0) as [398]
    ,isnull([104], 0) as [104]
    ,isnull([351], 0) as [351]
    ,isnull([436], 0) as [436]
    ,isnull([434], 0) as [434]
    ,isnull([384], 0) as [384]
    ,isnull([385], 0) as [385]
    ,isnull([377], 0) as [377]
    ,isnull([280], 0) as [280]
    ,isnull([395], 0) as [395]
 FROM (
    SELECT
        u.firstname AS 'first name',
        u.lastname AS 'last name',
        gi.idnumber AS 'examcode',
        gg.finalgrade AS 'grade'
    FROM mdl_grade_grades gg
    INNER JOIN mdl_grade_items gi ON gg.itemid = gi.id
    INNER JOIN mdl_user u ON gg.userid = u.id
    WHERE gi.idnumber IN ('148','414','413','228','359','379','398','104','351','436','434','384','385','377','280','395')
    AND gg.userid = '62750'
) SOURCE
PIVOT (
    MAX(grade)
    FOR examcode IN ([148],[414],[413],[228],[359],[379],[398],[104],[351],[436],[434],[384],[385],[377],[280],[395])
) PIVT
ORDER BY 'last name', 'first name'

在表示层处理这样的表示问题要好得多。但是,如果不能,则必须更改查询,因为PIVOT不直接支持表达式。一些选择:

选项1-嵌套轴:

选项2-MAXCASE:

选项3-动态SQL-添加/删除课程更加灵活,只需指定一次课程列表,根据读者的不同,可能更容易/更难阅读

DECLARE @userid varchar(11) = '62750', @sql nvarchar(max) = N'SELECT 
  [first name] = firstname, 
  [last name]  = lastname';

CREATE TABLE #g(i int IDENTITY(1,1), id varchar(4));

INSERT #g VALUES ('148'),('414'),('413'),('228'),('359'),('379'),('398'),('104'),
                 ('351'),('436'),('434'),('384'),('385'),('377'),('280'),('395');

SELECT @sql += N',
  ' + QUOTENAME(id) + N' = COALESCE(MAX(CASE i WHEN ''' 
  + id + ''' THEN grade END),''None'')'
FROM #g ORDER BY i;

SET @sql += N'
FROM 
(
  SELECT u.firstname, u.lastname, gi.idnumber AS i, 
    grade = CONVERT(varchar(11), gg.finalgrade)
  FROM dbo.mdl_grade_grades AS gg
  INNER JOIN dbo.mdl_grade_items AS gi 
    ON gg.itemid = gi.id
  INNER JOIN dbo.mdl_user AS u 
    ON gg.userid = u.id
  INNER JOIN #g AS g
    ON g.id = gi.idnumber
  WHERE gg.userid = @userid
) AS x
GROUP BY lastname, firstname
ORDER BY lastname, firstname;';

EXEC sys.sp_executesql @sql, N'@userid varchar(11)', @userid;

DROP TABLE #g;

有很多方法可以做到这一点,但它们要么丑陋要么不直观,有时两者兼而有之。这是因为T-SQL并不是为了美化表示——这就是HTML、CSS、JavaScript和其他客户端技术的用途。此外,您应该将数字存储为数字,并将其视为数字。而且,不要使用“姓氏”——改为使用[姓氏]更安全。

在表示层处理这样的表示问题要好得多。但是,如果不能,则必须更改查询,因为PIVOT不直接支持表达式。一些选择:

选项1-嵌套轴:

选项2-MAXCASE:

选项3-动态SQL-添加/删除课程更加灵活,只需指定一次课程列表,根据读者的不同,可能更容易/更难阅读

DECLARE @userid varchar(11) = '62750', @sql nvarchar(max) = N'SELECT 
  [first name] = firstname, 
  [last name]  = lastname';

CREATE TABLE #g(i int IDENTITY(1,1), id varchar(4));

INSERT #g VALUES ('148'),('414'),('413'),('228'),('359'),('379'),('398'),('104'),
                 ('351'),('436'),('434'),('384'),('385'),('377'),('280'),('395');

SELECT @sql += N',
  ' + QUOTENAME(id) + N' = COALESCE(MAX(CASE i WHEN ''' 
  + id + ''' THEN grade END),''None'')'
FROM #g ORDER BY i;

SET @sql += N'
FROM 
(
  SELECT u.firstname, u.lastname, gi.idnumber AS i, 
    grade = CONVERT(varchar(11), gg.finalgrade)
  FROM dbo.mdl_grade_grades AS gg
  INNER JOIN dbo.mdl_grade_items AS gi 
    ON gg.itemid = gi.id
  INNER JOIN dbo.mdl_user AS u 
    ON gg.userid = u.id
  INNER JOIN #g AS g
    ON g.id = gi.idnumber
  WHERE gg.userid = @userid
) AS x
GROUP BY lastname, firstname
ORDER BY lastname, firstname;';

EXEC sys.sp_executesql @sql, N'@userid varchar(11)', @userid;

DROP TABLE #g;

有很多方法可以做到这一点,但它们要么丑陋要么不直观,有时两者兼而有之。这是因为T-SQL并不是为了美化表示——这就是HTML、CSS、JavaScript和其他客户端技术的用途。此外,您应该将数字存储为数字,并将其视为数字。而且,不要使用“姓氏”——改为使用[姓氏]要安全得多。

另一种选择是通过交叉连接创建可能组合的子集,然后在枢轴中,我们进行一个UNION ALL

范例


另一个选择是通过交叉连接创建可能组合的子集,然后在枢轴中,我们进行一个UNION ALL

范例


那么,呈现HTML的代码是什么?该代码不能只说如果一个值为null,就改为“无”吗?要使用COALESCE[359],“None”必须从PIVOT更改为dynamic PIVOT或MAXCASE。不,我不能在html端执行null到None的转换。@luisdev,你能详细说明为什么不可能吗?这将不适合您的网页可能使用的任何i18n…我没有使用任何html。我想运行这个查询来生成一个.csv文件。那么是什么代码呈现HTML呢?该代码不能只说如果一个值为null,就改为“无”吗?要使用COALESCE[359],“None”必须从PIVOT更改为dynamic PIVOT或MAXCASE。不,我不能在html端执行null到None的转换。@luisdev,你能详细说明为什么不可能吗?这将不适合您的网页可能使用的任何i18n…我没有使用任何html。我想运行查询以生成一个.csv文件。