SQL查询需要显示空值

时间:2012-04-16 11:48:31

标签: sql tsql null

我正在使用SQL Server manager 2008。

我的查询如下:

SELECT dbo.iLines.Part,
   dbo.iLines.Pg,
   SUM(dbo.iLines.Qty) as sales6months,
   dbo.iLines.Prefix       
FROM 
   Autopart.dbo.iLines
RIGHT JOIN
   dbo.product  
ON
   dbo.product.keycode = dbo.ilines.part                 

where  prefix = 'i'
   and ([datetime] > dateadd(month, -6, getdate()))
   and dbo.ilines.part = 'BK939'

group by 
   dbo.ilines.pg,
   dbo.ilines.part,
   dbo.ilines.prefix

order by sales6months desc

因此,为了解释,我希望在产品表中的所有产品上获得最后6个月的销售额。

问题在于某些产品没有任何销售。我仍然需要它们来展示。 所以我要问的是显示所有产品的最后6个月销售额,包括0个销售额。

" iLines"是导致问题的表格,因为如果有销售,零件编号只存在于那里。

我知道可能有一种方法可以进行多次查询等。但我只需要1次查询就可以了。

我试过让null通过,但什么也没做,加上它真的很可怕使用空值呵呵。

要添加到此查询的任何代码段都非常棒!!

非常感谢!

如果您还需要更多信息,请询问!

UPDATE! 对不起,日期仅存在于Ilines。

Ilines =销售表 产品=只是我们所有产品的表格

这是主要的查询,它意味着拉动顶部" n"在过去6个月内售出的零件。 它起作用,除了我说它没有显示没有出售的零件。

ALTER PROCEDURE [dbo].[MyPareto]
@pgParam varchar(255)
AS
SELECT
   i.pg,
   dbo.OldParetoAnalysis.Pareto,
   i.part,
   i.sales6months,
   a.LostSales6Months,
   dbo.NewParetoAnalysis.Pareto

FROM
OPENQUERY(SACBAUTO, 'SELECT dbo.iLines.Part,
                            dbo.iLines.Pg,
                            SUM(dbo.iLines.Qty) as   sales6months,
                            dbo.iLines.Prefix 
                     FROM Autopart.dbo.iLines 
                     where prefix = ''i''
                     and [datetime] > dateadd(month, -6,    getdate())
                     group by 
                     dbo.ilines.pg,
                     dbo.ilines.part,
                     dbo.ilines.prefix
                     order by sales6months desc') i
RIGHT JOIN
dbo.OldParetoAnalysis
on
i.part collate SQL_Latin1_General_CP1_CI_AS = dbo.OldParetoAnalysis.Part
INNER JOIN
dbo.NewParetoAnalysis
ON
dbo.OldParetoAnalysis.Part collate SQL_Latin1_General_CP1_CI_AS =     dbo.NewParetoAnalysis.Part
LEFT JOIN
OPENQUERY(SACBAUTO, 'SELECT dbo.aLines.Part,
                            dbo.aLines.Pg,
                            SUM(dbo.aLines.Qty) as LostSales6Months,
                            dbo.aLines.Prefix 
                     FROM Autopart.dbo.aLines 
                     where prefix = ''d''
                     and [datetime] > dateadd(month, -6, getdate())
                     group by 
                     dbo.alines.pg,
                     dbo.alines.part,
                     dbo.alines.prefix
                     order by LostSales6Months desc') a
ON
dbo.NewParetoAnalysis.Part collate SQL_Latin1_General_CP1_CI_AS = a.part
WHERE
    i.pg = @pgParam
GROUP BY
   i.pg,
   dbo.OldParetoAnalysis.Pareto,
   i.part,
   i.sales6months,
   a.LostSales6Months,
   dbo.NewParetoAnalysis.Pareto
ORDER BY
dbo.OldParetoAnalysis.Pareto asc
将pareto视为最佳部分的联盟。 希望这会有所帮助,我试图避免添加它,因为它可能会让一些人不予评论。

好的新更新,这个打开的查询有效!​​!!

SELECT                      
                        dbo.product.Keycode,
                        dbo.iLines.Pg,
                        SUM(COALESCE(dbo.iLines.Qty, 0)) as sales6months,
                        dbo.iLines.Prefix 
                     FROM 
                        Autopart.dbo.product
                     LEFT OUTER JOIN
                        Autopart.dbo.ilines
                     ON
                        dbo.product.keycode = dbo.ilines.part
                        AND ([datetime] > dateadd(month, -6, getdate()) OR [datetime] is null )
                     WHERE
                        (dbo.iLines.Prefix = 'i' OR dbo.iLines.Prefix is null)
                        AND dbo.product.keycode = 'BK939'
                     group by 
                        dbo.ilines.pg,
                        dbo.product.keycode,
                        dbo.ilines.prefix
                     order by sales6months desc#

但是当我加入我的帕累托表时如下:

SELECT
   i.pg,
   dbo.OldParetoAnalysis.Pareto,
   i.keycode,
   i.sales6months


FROM
OPENQUERY(SACBAUTO, 'SELECT                     
                        dbo.product.Keycode,
                        dbo.iLines.Pg,
                        SUM(COALESCE(dbo.iLines.Qty, 0)) as sales6months,
                        dbo.iLines.Prefix 
                     FROM 
                        Autopart.dbo.product
                     LEFT OUTER JOIN
                        Autopart.dbo.ilines
                     ON
                        dbo.product.keycode = dbo.ilines.part
                        AND ([datetime] > dateadd(month, -6, getdate()) OR [datetime] is null )/* must be this*/
                     WHERE
                        (dbo.iLines.Prefix = ''i'' OR dbo.iLines.Prefix is null)
                     group by 
                        dbo.ilines.pg,
                        dbo.product.keycode,
                        dbo.ilines.prefix
                     order by sales6months desc') i
LEFT JOIN
dbo.OldParetoAnalysis
on
i.keycode collate SQL_Latin1_General_CP1_CI_AS = dbo.OldParetoAnalysis.Part
WHERE i.pg = '40' AND i.keycode = 'BK939'

结果回归相同,所以这意味着问题是当我去加入时,但是老帕累托确实包含了部件号,而且我也试过改变连接....我希望这会缩小搜索范围对于这个问题我希望有人知道为什么会发生这种情况!

最终更新! 哇这是looong,但最后我想出了问题,我不得不重新检查产品表PG字段!!!!!因为它不会是空的!这是代码!

ALTER PROCEDURE [dbo].[MyPareto32TEST]
@pgParam varchar(255)

AS
SELECT
   i.pg,
   dbo.OldParetoAnalysis.Pareto,
   i.keycode,
   i.sales6months,
   a.LostSales6Months,
   dbo.NewParetoAnalysis.Pareto

FROM
OPENQUERY(SACBAUTO, 'SELECT                      
                    dbo.product.Keycode,
                    dbo.iLines.Pg,
                    dbo.product.pg as ppg,
                    SUM(COALESCE(dbo.iLines.Qty, 0)) as sales6months,
                    dbo.iLines.Prefix 
                 FROM 
                    Autopart.dbo.product
                 LEFT OUTER JOIN
                    Autopart.dbo.ilines
                 ON
                    dbo.product.keycode = dbo.ilines.part
                    AND ([datetime] > dateadd(month, -6, getdate()) OR [datetime] is null )
                 WHERE
                    (dbo.iLines.Prefix = ''i'' OR dbo.iLines.Prefix is null)
                 group by 
                    dbo.ilines.pg,
                    dbo.product.keycode,
                    dbo.ilines.prefix,
                    dbo.product.pg
                 order by sales6months desc') i
RIGHT JOIN
dbo.OldParetoAnalysis
on
i.keycode collate SQL_Latin1_General_CP1_CI_AS = dbo.OldParetoAnalysis.Part
AND (i.pg = @pgParam or (i.pg is null AND i.ppg  = @pgParam))
INNER JOIN
dbo.NewParetoAnalysis
ON
dbo.OldParetoAnalysis.Part collate SQL_Latin1_General_CP1_CI_AS =   dbo.NewParetoAnalysis.Part

LEFT JOIN
OPENQUERY(SACBAUTO, 'SELECT                      
                    dbo.product.Keycode,
                    dbo.aLines.Pg,
                    SUM(COALESCE(dbo.aLines.Qty, 0)) as lostsales6months,
                    dbo.aLines.Prefix 
                 FROM 
                    Autopart.dbo.product
                 LEFT OUTER JOIN
                    Autopart.dbo.alines
                 ON
                    dbo.product.keycode = dbo.alines.part
                    AND ([datetime] > dateadd(month, -6, getdate()) OR [datetime] is null )
                 WHERE
                    (dbo.aLines.Prefix = ''d'' OR dbo.aLines.Prefix is null)
                 group by 
                    dbo.alines.pg,
                    dbo.product.keycode,
                    dbo.alines.prefix
                 order by lostsales6months desc') a
ON
dbo.NewParetoAnalysis.Part collate SQL_Latin1_General_CP1_CI_AS = a.keycode
WHERE(i.pg = @pgParam or (i.pg is null AND i.ppg  = @pgParam) AND dbo.NewParetoAnalysis.Pareto is not null)
GROUP BY
   i.pg,
   dbo.OldParetoAnalysis.Pareto,
   i.keycode,
   i.sales6months,
   a.LostSales6Months,
   dbo.NewParetoAnalysis.Pareto
ORDER BY
dbo.OldParetoAnalysis.Pareto asc

8 个答案:

答案 0 :(得分:5)

以下条件会过滤掉right join失败的任何行:

dbo.ilines.part = 'BK939'

要解决此问题,请将条件移至联接:

RIGHT JOIN
   dbo.product  
ON
   dbo.product.keycode = dbo.ilines.part                 
   and dbo.ilines.prefix = 'i'
   and dbo.ilines.part = 'BK939'
where  
   ([datetime] > dateadd(month, -6, getdate()))

假设[datetime]product的列,您可以将其保留在where子句中。

答案 1 :(得分:3)

我会从你想要的表格和我自己做的工作开始joins。你说你想要product。为什么不从该表开始,然后将LEFT JOIN带到iLines

也许这样的话:

SELECT 
    dbo.product.keycode AS part,
    dbo.iLines.Pg,
    SUM(dbo.iLines.Qty) as sales6months,
    dbo.iLines.Prefix       
FROM 
   dbo.product 
LEFT JOIN dbo.ilines  
    ON dbo.product.keycode = dbo.ilines.part
    AND dbo.ilines.prefix = 'i'
    and dbo.ilines.part = 'BK939'                 

where
    ([datetime] > dateadd(month, -6, getdate()))

group by 
   dbo.ilines.pg,
   dbo.product.keycode,
   dbo.ilines.prefix

order by sales6months desc

我不知道[datetime]列是来自product表,还是来自ilines表。如果它来自product表,那么上面的表可能适用。如果没有,那么也将它放在LEFT JOIN中。像这样:

LEFT JOIN dbo.ilines  
        ON dbo.product.keycode = dbo.ilines.part
        AND dbo.ilines.prefix = 'i'
        and dbo.ilines.part = 'BK939' 
        AND ([datetime] > dateadd(month, -6, getdate()))

修改

根据您的描述,您需要FULL OUTER JOIN。所以这次加入将是:

LEFT JOIN
dbo.OldParetoAnalysis
on
i.keycode collate SQL_Latin1_General_CP1_CI_AS = dbo.OldParetoAnalysis.Part

像这样:

FULL OUTER JOIN
dbo.OldParetoAnalysis
on
i.keycode collate SQL_Latin1_General_CP1_CI_AS = dbo.OldParetoAnalysis.Part

在msdn上它说:

  

通过在其中包含不匹配的行来保留不匹配的信息   连接的结果,使用完整的外连接。 SQL Server提供了   全外连接运算符,FULL OUTER JOIN,包括所有行   来自两个表,无论另一个表是否有   匹配价值。

参考here

<强> EDIT2

您是否尝试过正确加入dbo.OldParetoAnalysis?像这样:

RIGHT JOIN
dbo.OldParetoAnalysis
on
i.keycode collate SQL_Latin1_General_CP1_CI_AS = dbo.OldParetoAnalysis.Part

<强> EDIT3

您可以尝试的另一件事是创建临时表。这不是最好的解决方案。但也许是这样的:

CREATE TABLE #tmp 
(
    Keycode VARCHAR(100),
    Pg VARCHAR(100),
    sales6months INT,
    Prefix VARCHAR(100)
)

然后插入OPENQUERY

中的行
INSERT INTO #tmp(Keycode,Pg,sales6months,Prefix)
SELECT
    i.Keycode,
    i.pg,
    i.sales6months
    i.Prefix,
FROM
    OPENQUERY(SACBAUTO, 'SELECT                     
                        dbo.product.Keycode,
                        dbo.iLines.Pg,
                        SUM(COALESCE(dbo.iLines.Qty, 0)) as sales6months,
                        dbo.iLines.Prefix 
                     FROM 
                        Autopart.dbo.product
                     LEFT OUTER JOIN
                        Autopart.dbo.ilines
                     ON
                        dbo.product.keycode = dbo.ilines.part
                        AND ([datetime] > dateadd(month, -6, getdate()) OR [datetime] is null )/* must be this*/
                     WHERE
                        (dbo.iLines.Prefix = ''i'' OR dbo.iLines.Prefix is null)
                     group by 
                        dbo.ilines.pg,
                        dbo.product.keycode,
                        dbo.ilines.prefix
                     order by sales6months desc') i

然后我们加入了临时表。像这样:

SELECT
    *
FROM
    #tmp AS i
    LEFT JOIN dbo.OldParetoAnalysis
    on
    i.keycode collate SQL_Latin1_General_CP1_CI_AS = dbo.OldParetoAnalysis.Part
    WHERE i.pg = '40' AND i.keycode = 'BK939'

请记住在完成后删除临时表。像这样:

DROP TABLE #tmp

<强> EDIT4

如果你有原始的商店程序,那么代码应该和你一起使用临时表soulution,那么这可能会有所帮助:

ALTER PROCEDURE [dbo].[MyPareto]
@pgParam varchar(255)
AS

CREATE TABLE #tmp
(
    Keycode VARCHAR(100),--The type I don't know
    Pg VARCHAR(100),--The type I don't know
    sales6months INT,--The type I don't know
    Prefix VARCHAR(100)--The type I don't know
)
INSERT INTO #tmp(Keycode,Pg,sales6months,Prefix)
SELECT
    i.Keycode,
    i.pg,
    i.sales6months,
    i.Prefix
FROM
    OPENQUERY(SACBAUTO, 'SELECT                     
                        dbo.product.Keycode,
                        dbo.iLines.Pg,
                        SUM(COALESCE(dbo.iLines.Qty, 0)) as sales6months,
                        dbo.iLines.Prefix 
                     FROM 
                        Autopart.dbo.product
                     LEFT OUTER JOIN
                        Autopart.dbo.ilines
                     ON
                        dbo.product.keycode = dbo.ilines.part
                        AND ([datetime] > dateadd(month, -6, getdate()) OR [datetime] is null )/* must be this*/
                     WHERE
                        (dbo.iLines.Prefix = ''i'' OR dbo.iLines.Prefix is null)
                     group by 
                        dbo.ilines.pg,
                        dbo.product.keycode,
                        dbo.ilines.prefix
                     order by sales6months desc') i

SELECT
   i.pg,
   dbo.OldParetoAnalysis.Pareto,
   i.part,
   i.sales6months,
   a.LostSales6Months,
   dbo.NewParetoAnalysis.Pareto

FROM
#tmp i
RIGHT JOIN dbo.OldParetoAnalysis 
    on i.part collate SQL_Latin1_General_CP1_CI_AS = dbo.OldParetoAnalysis.Part
INNER JOIN dbo.NewParetoAnalysis 
    ON dbo.OldParetoAnalysis.Part collate SQL_Latin1_General_CP1_CI_AS =     dbo.NewParetoAnalysis.Part
LEFT JOIN #tmp a 
    ON dbo.NewParetoAnalysis.Part collate SQL_Latin1_General_CP1_CI_AS = a.part
WHERE
    i.pg = @pgParam
GROUP BY
   i.pg,
   dbo.OldParetoAnalysis.Pareto,
   i.part,
   i.sales6months,
   a.LostSales6Months,
   dbo.NewParetoAnalysis.Pareto
ORDER BY
    dbo.OldParetoAnalysis.Pareto asc

DROP TABLE #tmp

答案 2 :(得分:3)

问题根源:怀疑子句条件限制了由于正确加入而原本会存在的数据。

可能的解决方案

  1. 使用或&amp; Null on where clause critieria
  2. 将whereclause移动到另一个示例中已经完成的连接条件)
  3. 使用联盟
  4. 这是在where子句上使用null。 (修改)我们似乎都错过了从PARTS中选择的选择!不是ilines。

    SELECT dbo.product.keycode as PART,
       dbo.iLines.Pg,
       SUM(coalesce(dbo.iLines.Qty,0)) as sales6months,
       dbo.iLines.Prefix       
    FROM 
       Autopart.dbo.iLines
    RIGHT JOIN
       dbo.product  
    ON
       dbo.product.keycode = dbo.ilines.part                 
    
    where  (prefix = 'i' or prefix is null)
       and (([datetime] > dateadd(month, -6, getdate())) OR [datetime] is null)
       and (dbo.ilines.part = 'BK939' or dbo.ilines.part is null)
    
    group by 
       dbo.ilines.pg,
       dbo.product.keycode,
       dbo.ilines.prefix
    
    order by sales6months desc
    

答案 3 :(得分:2)

你需要一个外部联接 - 像这样:

SELECT dbo.product.keycode, 
  dbo.iLines.Pg, 
  SUM(dbo.iLines.Qty) as sales6months, 
  dbo.iLines.Prefix        
FROM  
  dbo.product
  LEFT OUTER JOIN Autopart.dbo.iLines ON dbo.product.keycode = dbo.ilines.part                  

在您的查询中,您只选择prefix='i'的销售,这将自动排除没有销售的产品,因此我不确定您希望如何处理。

答案 4 :(得分:2)

您仍在过滤外部联接中可能为NULL的内容。在where子句中加入Pareto表之后:

WHERE i.pg = '40'

该列的源(在您的OPENQUERY语句中)是dbo.ILines,它是外部连接到产品的,因此如果产品没有出现在ILines集中,则为NULL。您可以尝试:

WHERE ISNULL(i.pg, '40') = '40'

当然,如果即使dbo.ILines表中存在记录,i.pg也可以为NULL,那么您可能需要在原始查询中包含ILines中的键,并执行以下操作:

WHERE ( i.pg = '40'
        OR i.<ILinesKeyField> IS NULL
      )

这确保即使你在dbo.ILines.Pg中有NULL并且NULL字段不是由于外连接,也会过滤掉不需要的行。

答案 5 :(得分:1)

为什么不从产品表中选择all并在Autopart.dbo.iLines上保持联接?这将为您提供所有产品,然后加入匹配且不匹配的iLines表。

答案 6 :(得分:0)

下面是代码,只需要从产品表和ilines中检查PG !!

ALTER PROCEDURE [dbo].[MyPareto32TEST]
@pgParam varchar(255)

AS
SELECT
   i.pg,
   dbo.OldParetoAnalysis.Pareto,
   i.keycode,
   i.sales6months,
   a.LostSales6Months,
   dbo.NewParetoAnalysis.Pareto

FROM
OPENQUERY(SACBAUTO, 'SELECT                      
                    dbo.product.Keycode,
                    dbo.iLines.Pg,
                    dbo.product.pg as ppg,
                    SUM(COALESCE(dbo.iLines.Qty, 0)) as sales6months,
                    dbo.iLines.Prefix 
                 FROM 
                    Autopart.dbo.product
                 LEFT OUTER JOIN
                    Autopart.dbo.ilines
                 ON
                    dbo.product.keycode = dbo.ilines.part
                    AND ([datetime] > dateadd(month, -6, getdate()) OR [datetime] is null )
                 WHERE
                    (dbo.iLines.Prefix = ''i'' OR dbo.iLines.Prefix is null)
                 group by 
                    dbo.ilines.pg,
                    dbo.product.keycode,
                    dbo.ilines.prefix,
                    dbo.product.pg
                 order by sales6months desc') i
RIGHT JOIN
dbo.OldParetoAnalysis
on
i.keycode collate SQL_Latin1_General_CP1_CI_AS = dbo.OldParetoAnalysis.Part
AND (i.pg = @pgParam or (i.pg is null AND i.ppg  = @pgParam))
INNER JOIN
dbo.NewParetoAnalysis
ON
dbo.OldParetoAnalysis.Part collate SQL_Latin1_General_CP1_CI_AS = dbo.NewParetoAnalysis.Part

LEFT JOIN
OPENQUERY(SACBAUTO, 'SELECT                      
                    dbo.product.Keycode,
                    dbo.aLines.Pg,
                    SUM(COALESCE(dbo.aLines.Qty, 0)) as lostsales6months,
                    dbo.aLines.Prefix 
                 FROM 
                    Autopart.dbo.product
                 LEFT OUTER JOIN
                    Autopart.dbo.alines
                 ON
                    dbo.product.keycode = dbo.alines.part
                    AND ([datetime] > dateadd(month, -6, getdate()) OR [datetime] is null )
                 WHERE
                    (dbo.aLines.Prefix = ''d'' OR dbo.aLines.Prefix is null)
                 group by 
                    dbo.alines.pg,
                    dbo.product.keycode,
                    dbo.alines.prefix
                 order by lostsales6months desc') a
ON
dbo.NewParetoAnalysis.Part collate SQL_Latin1_General_CP1_CI_AS = a.keycode
WHERE(i.pg = @pgParam or (i.pg is null AND i.ppg  = @pgParam) AND dbo.NewParetoAnalysis.Pareto is not null)
GROUP BY
   i.pg,
   dbo.OldParetoAnalysis.Pareto,
   i.keycode,
   i.sales6months,
   a.LostSales6Months,
   dbo.NewParetoAnalysis.Pareto
ORDER BY
dbo.OldParetoAnalysis.Pareto asc

答案 7 :(得分:-1)

SELECT
    dbo.iLines.Part,
    dbo.iLines.Pg,
    SUM(dbo.iLines.Qty) as sales6months,
    dbo.iLines.Prefix       
FROM Autopart.dbo.iLines
RIGHT JOIN dbo.product  
ON dbo.product.keycode = dbo.ilines.part
where  prefix = 'i'
and ([datetime] > dateadd(month, -6, getdate()))
and dbo.ilines.part = 'BK939'

group by 
    dbo.ilines.pg,
    dbo.ilines.part,
    dbo.ilines.prefix
union
SELECT
    dbo.iLines.Part,
    dbo.iLines.Pg,
    0 as sales6months,
    dbo.iLines.Prefix       
FROM Autopart.dbo.iLines
RIGHT JOIN dbo.product  
ON dbo.product.keycode = dbo.ilines.part
where  prefix = 'i'
and max([datetime]) < dateadd(month, -6, getdate())
and dbo.ilines.part = 'BK939'

group by 
    dbo.ilines.pg,
    dbo.ilines.part,
    dbo.ilines.prefix    
order by sales6months desc