0

構造が同じ5つのテーブルがあります。フィールドのみPAGEVISITSが一意です

すなわち。表1:

ITEM |   PAGEVISITS   |  Commodity
1813       50            Griddle
1851       10            Griddle
11875      100           Refrigerator
2255       25            Refrigerator

すなわち。表 2:

ITEM |   PAGEVISITS   |  Commodity
1813       0             Griddle
1851       10            Griddle
11875      25            Refrigerator
2255       10            Refrigerator

Commodity吐き出すために追加したい:

table1   |   table2   |  Commodity
60           10          Griddle
125          35          Refrigerator

一部のデータは実際には正しいですが、一部は以下のクエリを考えるとかなりずれています。

SELECT
SUM(MT.PAGEVISITS) as table1,
SUM(CT1.PAGEVISITS) as table2,
SUM(CT2.PAGEVISITS) as table3,
SUM(CT3.PAGEVISITS) as table4,
SUM(CT4.PAGEVISITS) as table5,
(COUNT(DISTINCT MT.ITEM)) + (COUNT(DISTINCT CT1.ITEM)) + (COUNT(DISTINCT CT2.ITEM)) + (COUNT(DISTINCT CT3.ITEM)) + (COUNT(DISTINCT CT4.ITEM)) as Total,
MT.Commodity
    FROM table1 as MT
       LEFT JOIN table2 CT1
       on MT.ITEM = CT1.ITEM
       LEFT JOIN table3 CT2
       on MT.ITEM = CT2.ITEM
       LEFT JOIN table4 CT3
       on MT.ITEM = CT3.ITEM
       LEFT JOIN table5 CT4
       on MT.ITEM = CT4.ITEM
GROUP BY Commodity

の使い方がLEFT JOIN間違っていることが原因だと思います。私もINNER JOIN同じ一貫性のない結果で試しました。

4

1 に答える 1

2

これらのテーブルの 5 つすべてに対して UNION を実行して、それらを 1 つの行セット (インライン ビュー) として取得し、その上でクエリを実行して、次のようなものから始めます...

SELECT SUM(IF(t.source='MT',t.pagevisits,0)) AS table1
     , SUM(IF(t.source='CT1',t.pagevisits,0)) AS table2
     , t.commodity
  FROM ( SELECT 'MT' as source, table1.* FROM table1 
          UNION ALL  
         SELECT 'CT1', table2.* FROM table2
          UNION ALL
         SELECT 'CT2', table3.* FROM table3
          UNION ALL
         SELECT 'CT3', table4.* FROM table4
          UNION ALL
         SELECT 'CT4', table5.* FROM table5
      ) t
GROUP BY t.commodity

(ただし、「.*」を使用して、これらのテーブルの列の追加/削除/名前変更/並べ替えを行わないことにクエリを依存させるのではなく、これらのテーブルごとに列リストを指定します。)

行がどのテーブルから来たかを識別するために、「余分な」リテラル値 (「ソース」としてエイリアス) を含めます。SELECT リストの式で条件付きテストを使用して、その行が特定のテーブルからのものかどうかを判断できます。

このアプローチは特に柔軟で、より複雑な結果セットを取得するために使用できます。たとえば、テーブル 3、4、および 5 から合計ページ アクセス数も取得したい場合は、個々のカウントと共に合計します。

SUM(IF(t.source IN ('CT2','CT3','CT4'),t.pagevisits,0) AS total_345

あなたのCOUNT(DISTINCT item) + COUNT(DISTINCT item) + ...表現に相当するものを得るには...

「ソース」列と「アイテム」列の両方から単一の値を作成する式を使用しますが、特定の「ソース」+「アイテム」が他の「ソース」の複製を作成しないという何らかの保証があるように注意してください。 「+」アイテム」。(たとえば、文字列を連結するだけでは、'A'+'11' と 'A1'+'1' を区別する方法がありません。) ここで目にする最も一般的なアプローチは、慎重に選択された区切り文字です。どちらの値にも表示されないことが保証されています。'A::11' と 'A1::1' を区別できるため、次のようなものが機能します。

 COUNT(DISINCT CONCAT(t.source,'::',t.item))

現在のクエリでは、itemが NULL の場合、行は COUNT に含まれません。その動作を完全に再現するには、次のようなものが必要です。

 COUNT(DISINCT IF(t.item IS NOT NULL,CONCAT(t.source,'::',t.item),NULL)) AS Total

もちろん、5 つのテーブルのセット全体で個別のアイテム値の数を取得する方がはるかに簡単です (ただし、別の結果が返されます)。

 COUNT(DISINCT t.item)

しかし、の使用に関する質問に答えるにはLEFT JOIN、左側のテーブルが「ドライバー」であるため、右側のテーブルから対応する行を取得するには、一致する行がそのテーブルに存在する必要があります。つまり、右側のテーブルの一致しない行は返されません。

あなたが持っているものが基本的に5つの「パーティション」であり、一致する行が他の「パーティション」のいずれかに表示されるかどうかに関係なく、すべての行を処理したい場合は、UNION ALLすべての行を単純に連結するアプローチを使用しますこれらのテーブルをすべてまとめて、単一のテーブルからのものであるかのように行を処理します。

注: 非常に大きなテーブルの場合、MySQL がそのインライン ビューを具体化する必要があるため、これは実行可能なアプローチではない可能性があります。すべての行を連結する必要のない他のアプローチがあります。

必要な列のみのリストを各テーブルの SELECT で指定すると、クエリで参照する必要のない列がテーブルにある場合、パフォーマンスが向上する可能性があります。


于 2012-07-17T15:54:50.180 に答える