1. ホーム
  2. sql

[解決済み] マルチパート識別子をバインドできなかった

2022-02-05 19:41:35

質問

SOで同じようなエラーを見ましたが、私の問題に対する解決策が見つかりません。 私は次のようなSQLクエリを持っています。

SELECT DISTINCT
        a.maxa ,
        b.mahuyen ,
        a.tenxa ,
        b.tenhuyen ,
        ISNULL(dkcd.tong, 0) AS tongdkcd
FROM    phuongxa a ,
        quanhuyen b
        LEFT OUTER JOIN ( SELECT    maxa ,
                                    COUNT(*) AS tong
                          FROM      khaosat
                          WHERE     CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                                              AND
                                                              'Sep 5 2011'
                          GROUP BY  maxa
                        ) AS dkcd ON dkcd.maxa = a.maxa
WHERE   a.maxa <> '99'
        AND LEFT(a.maxa, 2) = b.mahuyen
ORDER BY maxa;

このクエリを実行すると、エラー結果になります。 マルチパート識別子 "a.maxa" をバインドできませんでした。 なぜですか?
P/s: クエリを2つの個別のクエリに分割すると、それはうまく実行されます。

SELECT DISTINCT
        a.maxa ,
        b.mahuyen ,
        a.tenxa ,
        b.tenhuyen
FROM    phuongxa a ,
        quanhuyen b
WHERE   a.maxa <> '99'
        AND LEFT(a.maxa, 2) = b.mahuyen
ORDER BY maxa;

そして

SELECT  maxa ,
        COUNT(*) AS tong
FROM    khaosat
WHERE   CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                        AND     'Sep 5 2011'
GROUP BY maxa;

解決方法は?

暗黙的な結合と明示的な結合を混在させています。それは許されることですが、それを適切に行う方法を知っておく必要があります。

つまり、明示的な結合(これは、(1)と(2)を使って実装されるものです。 JOIN キーワード) は、暗黙的なもの (コンマ結合、結合条件が WHERE 節を含む)。

クエリの概要はこんな感じです。

SELECT
  …
FROM a, b LEFT JOIN dkcd ON …
WHERE …

おそらく、このような挙動を期待しているのでしょう。

SELECT
  …
FROM (a, b) LEFT JOIN dkcd ON …
WHERE …

つまり、テーブルの組み合わせ ab がテーブルと結合している dkcd . 実際には、次のようなことが起こっています。

SELECT
  …
FROM a, (b LEFT JOIN dkcd ON …)
WHERE …

というのは、もうお分かりかもしれませんが dkcd に対して特別に結合されています。 b のみであり b というように、結合の結果を a でさらにフィルタリングし WHERE 節があります。この場合、すべての参照先が a の中で ON 節は無効です。 a はその時点では不明です。そのため、エラーメッセージが表示されるのです。

もし私があなただったら、このクエリを書き換えてみると思いますが、一つの可能性があるかもしれません。

SELECT DISTINCT
  a.maxa,
  b.mahuyen,
  a.tenxa,
  b.tenhuyen,
  ISNULL(dkcd.tong, 0) AS tongdkcd
FROM phuongxa a
  INNER JOIN quanhuyen b ON LEFT(a.maxa, 2) = b.mahuyen
  LEFT OUTER JOIN (
    SELECT
      maxa,
      COUNT(*) AS tong
    FROM khaosat
    WHERE CONVERT(datetime, ngaylap, 103) BETWEEN 'Sep 1 2011' AND 'Sep 5 2011'
    GROUP BY maxa
  ) AS dkcd ON dkcd.maxa = a.maxa
WHERE a.maxa <> '99'
ORDER BY a.maxa

ここでは、テーブル ab がまず結合され、その結果が dkcd . 基本的に、これはあなたと同じクエリですが、結合の1つに異なる構文を使用しており、これが大きな違いを生んでいます。 a.maxa の中の dkcd の結合条件が絶対的に有効になりました。

Aaron Bertrand が正しく指摘しているように、おそらくは maxa には、特定のエイリアス、おそらく a の中にある ORDER BY 節を使用します。