3

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 か月の売上を表示することです。

「iLines」は、販売があった場合にのみ部品番号がそこに存在するため、問題の原因となっているテーブルです。

複数のクエリなどを実行する方法があるかもしれないことは知っていますが、これはすべて1つのクエリでのみ必要です。

nullを通過させようとしましたが、何もしません。nullを使用すると本当に怖いです。

このクエリに追加するコード スニペットはどれも素晴らしいものです。

どうもありがとう!

また、さらに情報が必要な場合は、お問い合わせください。

アップデート!はい、申し訳ありませんが、Datetime は Ilines にのみ存在します。

Ilines = 売上表 Product = すべての製品の表

これが主なクエリです。これは、過去 6 か月間に販売された上位 "n" 個の部品を取得するためのものです。私が言ったように、売れていない部品は表示されません。

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

パレートを最良の部分のリーグと考えてください。これが役に立てば幸いです。一部の人がコメントを控える可能性があるため、追加しないようにしました。

わかりました新しい更新、この開いているクエリは機能します!!!

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'

結果は同じに戻ります。つまり、問題は参加するときにあることを意味しますが、古いパレートには部品番号が含まれており、結合を変更しようとしました....これで問題の検索が絞り込まれたことを願っていますなぜこれが起こっているのか、誰かが考えていることを願っています!

最終更新!うわー、これは長いですが、最終的に問題を理解しました。製品テーブルのPGフィールドを使用して再確認する必要がありました!!!!! nullにならないから!! これがコードです!

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
4

8 に答える 8

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

于 2012-04-16T11:56:14.123 に答える
3

I would start from the table you want and the work myself do to the joins. You said you want product. Why not start with that table and then take a LEFT JOIN to the iLines?

Maybe something like this then:

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

I don't know if the [datetime] column is coming from the product table or if is from the ilines table. If it is from the product table then the upper one will probably apply. If not then put that in the LEFT JOIN as well. Like this:

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()))

EDIT

It sound per your description that you want a FULL OUTER JOIN. So this join will be:

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

Like this:

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

On msdn it says:

To retain the nonmatching information by including nonmatching rows in the results of a join, use a full outer join. SQL Server provides the full outer join operator, FULL OUTER JOIN, which includes all rows from both tables, regardless of whether or not the other table has a matching value.

Reference here

EDIT2

Have you tried with a RIGHT JOIN to the dbo.OldParetoAnalysis? Like this:

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

EDIT3

On other thing you can try is that you create a temp table. It is not the neatest solution. But maybe something like this:

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

And then insert then rows from the 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

And then us the temp table in the joins. Like this:

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'

Remember to drop the temp table after you are done. Like this:

DROP TABLE #tmp

EDIT4

If you have the original store procedure then the code should and it you are going with the temp table soulution then this might be of help:

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
于 2012-04-16T11:58:13.407 に答える
3

問題の原因: where 句の条件が、そうでなければ右結合のためにそこにあるはずのデータを制限している可能性があります。

可能な解決策

  1. where 句の条件で or & Null を使用する
  2. whereclause を結合基準に移動します (別の例で既に行われています)。
  3. ユニオンを使用する

これは where 句で null を使用しています。(改訂版) 私たちは皆、PARTS からプルする必要がある選択を見逃しているように見えました! アイラインではありません。

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
于 2012-04-16T11:59:50.443 に答える
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'います。これにより、販売のない製品が自動的に除外されるため、それをどのように処理したいかわかりません。

于 2012-04-16T11:56:43.940 に答える
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 フィールドが外部結合によるものではない場合でも、不要な行がフィルタリングされます。

于 2012-04-19T21:26:53.233 に答える
1

製品テーブルからすべてを選択して、Autopart.dbo.iLines に結合しないのはなぜですか? これにより、すべての製品が得られ、一致する iLines テーブルと一致しない iLines テーブルに参加します。

于 2012-04-16T11:56:19.320 に答える
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
于 2012-04-23T11:03:58.107 に答える
-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
于 2012-04-16T11:56:22.747 に答える