1

私の目標は、1 つのクエリによって生成されたグループが、同じクエリの出力と同じグループであるかどうかをテストすることです。ただし、単一の変数名を変更すると、異なる結果が得られます。

以下に、結果が同じであることがわかっている同じクエリの例を示します。ただし、このグループを実行すると、クエリによって結果が異なることがわかります。

SELECT grp
FROM
(
  SELECT CONCAT(word, corpus) AS grp, rank1, rank2 
  FROM (
    SELECT
      word, corpus,
      ROW_NUMBER() OVER (PARTITION BY word ORDER BY test1 DESC) AS rank1,
      ROW_NUMBER() OVER (PARTITION BY word ORDER BY word_count DESC) AS rank2,
      ROW_NUMBER() OVER (PARTITION BY word ORDER BY corpus DESC) AS rank3,
      ROW_NUMBER() OVER (PARTITION BY word ORDER BY corpus_date DESC) AS rank4
    FROM 
    (
      SELECT *, (word_count * word_count * corpus_date) AS test1
      FROM [bigquery-public-data:samples.shakespeare]
    )
  )
)
WHERE rank1 <= 3 OR rank2 <= 3
HAVING grp NOT IN 
(
  SELECT grp FROM (
    SELECT CONCAT(word, corpus) AS grp, rank1, rank2
    FROM
    (
      SELECT
        word, corpus,
        ROW_NUMBER() OVER (PARTITION BY word ORDER BY test2 DESC) AS rank1,
        ROW_NUMBER() OVER (PARTITION BY word ORDER BY word_count DESC) AS rank2,
        ROW_NUMBER() OVER (PARTITION BY word ORDER BY corpus DESC) AS rank3,
        ROW_NUMBER() OVER (PARTITION BY word ORDER BY corpus_date DESC) AS rank4
      FROM 
      (
        SELECT *, (word_count * word_count * corpus_date) AS test2
        FROM [bigquery-public-data:samples.shakespeare]
      )
    )
  )
  WHERE rank1 <= 3 OR rank2 <= 3
)

さらに悪いことに、まったく同じクエリを実行しようとしても、変数名をtest1からtest3に変更すると、まったく異なる結果が得られます。

SELECT grp
FROM
(
  SELECT CONCAT(word, corpus) AS grp, rank1, rank2 
  FROM (
    SELECT
      word, corpus,
      ROW_NUMBER() OVER (PARTITION BY word ORDER BY test3 DESC) AS rank1,
      ROW_NUMBER() OVER (PARTITION BY word ORDER BY word_count DESC) AS rank2,
      ROW_NUMBER() OVER (PARTITION BY word ORDER BY corpus DESC) AS rank3,
      ROW_NUMBER() OVER (PARTITION BY word ORDER BY corpus_date DESC) AS rank4
    FROM 
    (
      SELECT *, (word_count * word_count * corpus_date) AS test3
      FROM [bigquery-public-data:samples.shakespeare]
    )
  )
)
WHERE rank1 <= 3 OR rank2 <= 3
HAVING grp NOT IN 
(
  SELECT grp FROM (
    SELECT CONCAT(word, corpus) AS grp, rank1, rank2
    FROM
    (
      SELECT
        word, corpus,
        ROW_NUMBER() OVER (PARTITION BY word ORDER BY test2 DESC) AS rank1,
        ROW_NUMBER() OVER (PARTITION BY word ORDER BY word_count DESC) AS rank2,
        ROW_NUMBER() OVER (PARTITION BY word ORDER BY corpus DESC) AS rank3,
        ROW_NUMBER() OVER (PARTITION BY word ORDER BY corpus_date DESC) AS rank4
      FROM 
      (
        SELECT *, (word_count * word_count * corpus_date) AS test2
        FROM [bigquery-public-data:samples.shakespeare]
      )
    )
  )
  WHERE rank1 <= 3 OR rank2 <= 3
)

これらの奇妙な動作の両方を満たす説明は考えられず、これがデータの検証を妨げています。何か案は?

編集

応答が示唆する方法で BigQuery SQL を更新しましたが、同じ不整合が発生します。

4

3 に答える 3

2

問題は、行番号付けの非決定性です。

この表に(word_count * word_count * corpus_date)は、複数のコーパスで が同じである多くの例があります。したがって、 partition bywordおよび order bytest2の場合、行番号の割り当てに使用する順序付けは非決定論的です。

同じトップレベル クエリ内で同じサブクエリを 2 回実行すると、BigQuery は実際にはそのサブクエリを 2 回実行し、その非決定性のために 2 回の実行で異なる結果が生じる可能性があります。

エイリアスを変更すると、クエリがキャッシュにヒットしない可能性があり、その結果、非決定論的な選択のセットが異なり、結果間のオーバーラップの量が異なります。

ORDER BYこれは、分析関数の句を include に変更することで確認できますcorpus。たとえば、 に変更ORDER BY test2ORDER BY test2, corpusます。行の番号付けは決定論的になり、使用するエイリアスに関係なく、クエリはゼロの結果を返します。

于 2016-04-21T09:53:20.953 に答える
1

質問がわかりません。一般的な SQL 構文と特に BigQuery はどちらも非常に明確です。 で定義されたエイリアスは、 for 他の式SELECTでは使用できません。BigQueryのドキュメントSELECTで説明されているように:

句で定義されたエイリアスは、クエリの 、 、および句でSELECT参照できますが、 、、または句や、同じ句内の他の式では参照できません。[鉱山を強調]GROUP BYHAVINGORDER BYFROMWHEREOMIT RECORD IFSELECT

したがって、クエリはtest1、 、test2、およびtest3が Shakespeare テーブルの列である場合にのみ機能します。そのような列が同様の値を持つと考える理由はないので、クエリが同じ結果を返すとは思わないでしょう。

編集:

ドキュメントが正しくないと仮定すると、問題はおそらく のorder by基準で重複していますrow_number()。SQL での並べ替えは安定していません。つまり、並べ替え中に同じ並べ替えキー値を持つ 2 つの行が任意の順序で表示される可能性があります。同じクエリでも、2 回実行すると異なる結果が返されることがあります。テーブルには行間に固有の順序がないため、SQL ソートは明らかに安定していません (順序は列によってのみ指定されます)。

したがって、同じソートキー値を持つ異なる行が選択されているだけです。これはエイリアスとは関係ないと思います。

どうすればこれを修正できますか? などの追加idソートキーを最終キーとしてソートに追加します。あるいは、rank()orを使用dense_rank()して、重複をどう処理するかを明示的に把握します。

于 2016-04-20T19:41:28.243 に答える
1

あなたはいつも厳しい質問をしているのに、回答を受け入れることも、投票することさえも難しいことに気付きました。それで大丈夫です!そして、もう一度やり直したいので、件名に行きましょう:

同じ SELECT ステートメントでエイリアスを使用することは文書化されておらず、サポートされていないようです。以下のSELECT 句のドキュメントに注意してください。

式の後にスペースと識別子を追加することで、各式に別名を付けることができます。オプションの AS キーワードを式とエイリアスの間に追加して、読みやすくすることができます。SELECT 句で定義されたエイリアスは、クエリの GROUP BY、HAVING、および ORDER BY 句で参照できますが、FROM、WHERE、または OMIT RECORD IF 句や、同じ SELECT 句内の他の式では参照できません。

したがって、エラーをスローすることなく、ここで奇妙な動作が発生します。したがって、自己責任で使用することはできますが、使用しないことをお勧めします (それでも Google チームからの連絡をお待ちしております。ただし、サポートされていないため、この動作を説明する情報はあまり期待できません)。

それまでの間-サポートされているものに従って、クエリを「安定した」バージョン以下に変換することをお勧めします。
オリジナルで直面する問題はありません。
(最初のサブクエリで WHERE 句を変更したことに注意してください。そうしないと、常にゼロ行が返されます。これは完全に理にかなっています)

SELECT grp
FROM
(
  SELECT CONCAT(word, corpus) AS grp, rank2, 
    ROW_NUMBER() OVER (PARTITION BY word ORDER BY [try_any_alias_1] DESC) AS rank1
  FROM (
    SELECT
      word, corpus,
      (word_count * word_count * corpus_date) AS [try_any_alias_1],
      ROW_NUMBER() OVER (PARTITION BY word ORDER BY word_count DESC) AS rank2,
      ROW_NUMBER() OVER (PARTITION BY word ORDER BY corpus DESC) AS rank3,
      ROW_NUMBER() OVER (PARTITION BY word ORDER BY corpus_date DESC) AS rank4
    FROM [bigquery-public-data:samples.shakespeare]
  )
)
WHERE rank1 <= 3 OR rank2 <= 4 // if rank2 <= 3 as in second subquery - result is always empty as expected
HAVING grp NOT IN 
(
  SELECT grp FROM (
    SELECT CONCAT(word, corpus) AS grp, rank2,
      ROW_NUMBER() OVER (PARTITION BY word ORDER BY [try_any_alias_2] DESC) AS rank1
    FROM
    (
      SELECT
        word, corpus,
        (word_count * word_count * corpus_date) AS [try_any_alias_2],
        ROW_NUMBER() OVER (PARTITION BY word ORDER BY word_count DESC) AS rank2,
        ROW_NUMBER() OVER (PARTITION BY word ORDER BY corpus DESC) AS rank3,
        ROW_NUMBER() OVER (PARTITION BY word ORDER BY corpus_date DESC) AS rank4
      FROM [bigquery-public-data:samples.shakespeare]
    )
  )
  WHERE rank1 <= 3 OR rank2 <= 3
)
于 2016-04-20T20:50:56.217 に答える