1. ホーム
  2. データベース
  3. マイサク

[解決済み】マルチパート識別子をバインドできませんでした。

2021-12-28 21:29:28

質問内容

最近、次のような 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" をバインドできませんでした。
このクエリを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;

解決方法は?

SQLクエリで暗黙的結合と明示的結合を混在させることは何も問題ありませんが、正しい方法を知っておく必要があります。

明示的な結合(この場合は 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 はその時点では不明です。そのため、エラーメッセージが表示されるのです。

この問題を解決するために、SQLクエリを次のように書き直しました。

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 節を使用します。