我已经设置了一个视图,它将多个表中的所有数据组合在一起。有没有办法写这个,以便只显示包含非空数据的列,并且不包括那些包含所有NULL值的列?
增加: 对不起,还在学习和开展我的第一个大项目,所以每天似乎都是一个新的体验。我不是很清楚,这部分是因为我不确定我会以正确的方式做事!客户是一个学术图书馆,数据库记录特定馆藏的详细信息。我提到的视图是显示有关项目的所有数据,因此它将出版物,副本,作者,出版商,语言等表格汇集在一起。该系列中的少量项目是论文,因此除标准书目详细信息外,还有其他详细信息。我不想要的是用户获取与论文相关的所有空白字段,如果返回的内容仅包括书籍,因此纸质表字段全部为空。所以我想也许有办法不展示这些。有人评论说这是客户端应用程序的工作而不是数据库本身,所以我可以保留这个,直到我进入项目的那个阶段。
答案 0 :(得分:3)
在sql中无法做到这一点。
答案 1 :(得分:1)
CREATE VIEW dbo.YourView
AS
SELECT (list of fields)
FROM dbo.Table1 t1
INNER JOIN dbo.Table2 t2 ON t1.ID = t2.FK_ID
WHERE t1.SomeColumn IS NOT NULL
AND t2.SomeOtherColumn IS NOT NULL
在视图定义中,您可以包含WHERE条件,这些条件可以排除某些列为NULL的行。
更新:您无法真正过滤列 - 您在视图定义中定义了视图中列的列列表,此列表已修复且无法动态更改.... ..
您可以做的是使用ISNULL(column, '')
构造来用空字符串替换这些NULL。或者你需要处理在显示器前端排除那些列 - 而不是在SQL视图定义中...
我看到你唯一能做的就是确保只从视图中选择那些你知道不是NULL的列:
SELECT (list of non-null fields) FROM dbo.YourView
WHERE (column1 IS NOT NULL)
等等 - 但是没有简单或神奇的方法可以在一个SELECT语句中选择所有非NULL的列...
答案 2 :(得分:1)
您无法在视图中执行此操作,但可以使用存储过程中的动态SQL轻松地执行此操作。
当然,拥有一个移位的模式对于使用数据的客户来说不一定有用,但如果你的数据非常稀疏并且消费客户端理解不同的模式,那么它会很有效。
如果您必须有一个视图,可以在视图中放置一个“标题”行,您可以在循环的第一行检查客户端,看看您是否不想打扰网格中的列或者其他什么,你可以这样做:
SELECT * FROM (
-- This is the view code
SELECT 'data' as typ
,int_col
,varchar_col
FROM TABLE
UNION ALL
SELECT 'hdr' as typ
-- note that different types have to be handled differently
,CASE WHEN COUNT(int_col) = 0 THEN NULL ELSE 0 END
,CASE WHEN COUNT(varchar_col) = 0 THEN NULL ELSE '' END
FROM TABLE
) AS X
-- have to get header row first
ORDER BY typ DESC -- add other sort criteria here
答案 3 :(得分:0)
通常,在查询中添加WHERE子句,例如
WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL
此处,b c是您的列名。
如果要在可能为NULL的列上将表连接在一起,则使用INNER JOIN,并且不会包含NULL值。
编辑:我可能误解了 - 上面会过滤掉行,但您可能会要求过滤掉列,例如:您有多个列,并且只希望显示在返回的所有行中包含至少一个空值的列。使用动态SQL提供了一种解决方案,因为设置的列会根据您的数据而变化。这是一个SQL查询,它构建另一个包含相应列的SQL查询。您可以运行此查询,然后将其结果作为另一个查询提交。它假定'pk'是一些总是非空的列,例如主键 - 这意味着我们可以使用逗号为其他行名添加前缀。
SELECT CONCAT("SELECT pk"
CASE (count(columnA)) WHEN 0 THEN '' ELSE ',columnA' END,
CASE (count(columnB)) WHEN 0 THEN '' ELSE ',columnB' END,
// etc..
' FROM (YourQuery) base')
FROM
(YourQuery) As base
查询使用Count(列)工作 - 聚合函数忽略NULL值,因此对于完全由NULL组成的列返回0。查询构建器假定YourQuery使用别名来确保没有重复的列名。
虽然您无法将其放入视图中,但您可以将其包装为将数据复制到另一个表(结果表)的存储过程。您还可以设置一个触发器,以便在基表更改时更新结果表。
答案 4 :(得分:0)
如果我们正确地阅读您的问题,则无法在SQL中执行此操作。视图的输出必须是关系 - 在(过度)简化术语中,它必须是矩形的。也就是说,每行必须具有相同的列数。
如果您可以告诉我们有关您的数据的更多信息并告诉我们您想要对输出做些什么,我们可以提供更多积极的建议。
答案 5 :(得分:0)
我怀疑最终用户正在运行CrystalReports并抱怨所有必须手动删除的空列。
实际上可以创建一个可以动态创建视图的存储过程,而不会创建无数据列。但是在使用视图之前你必须运行这个proc。
这可以接受吗?