2017-06-15 25 views
-1

これを行う最も良い方法は何ですか?複数のMySQLクエリの結果を1つのテーブルで結合する

私は以下の記述が、ここで私は基本的に修理の仕事上の情報が含まれている「例」と呼ばれるテーブルを持っている http://rextester.com/PXQOV60475

with-再生するrextester.comデータで設定されます。ケースマネージャーには "case_mgr"というフィールドと "case_mgr_first"フィールドがあります。これは、ケースマネージャーを変更してオリジナルに含まれるようにすることができるからです。 "who_last_called"には、顧客に最後に連絡したユーザーである別の同様のフィールドがあります。それらはすべてユーザー名を含んでいます... "case_mgr_first"と "who_last_called"はnullでもかまいません( "case_mgr_first"は新しいフィールドであり、誰も呼び出されていない可能性があります)。

修復作業を続行するには、修理するアイテムを受け取る必要があります。それが受信されると、 "item_received_date"フィールドが設定され、それ以外の場合はnullになります。また、レコードが作成された日がフィールド "created_date"に保存されています。

だから、目的は、ユーザーの受信%を複数の方法で見つけることです。私は現在のケースマネージャ( "case_mgr")として、 "case_mgr_first"として、そして "who_last_called"として、 "created_date"によって特定の期間、この受信レートを探したいと思います。

私はすでにこれらのいずれかのクエリを取得しており、うまくいきました。

"case_mgr_first" で行くとき、私は同じことをしてくれresult-

+-----------+-----------+------------+--------------+ 
| case_mgr | count_new | count_recd | percent_recd | 
+-----------+-----------+------------+--------------+ 
| bamm-bamm |  10 |   4 | 40.00  | 
| barney |  105 |   43 | 40.95  | 
| betty  |  120 |   60 | 50.00  | 
| fred  |  139 |   54 | 38.85  | 
| wilma  |  97 |   56 | 57.73  | 
+-----------+-----------+------------+--------------+ 

を与える

SELECT c.case_mgr AS case_mgr, COUNT(*) AS count_new, 
SUM(CASE WHEN c.item_received_date IS NOT NULL THEN 1 ELSE 0 END) AS count_recd, 
SUM(CASE WHEN c.item_received_date IS NOT NULL THEN 1 ELSE 0 END)*100/COUNT(*) AS percent_recd 
FROM cases c WHERE (c.created_date >= '2017-05-01 00:00:00' AND c.created_date <= '2017-05-31 23:59:59') 
GROUP BY c.case_mgr ORDER BY c.case_mgr ASC 

SELECT c.case_mgr_first AS case_mgr_first, COUNT(*) AS count_new, 
SUM(CASE WHEN c.item_received_date IS NOT NULL THEN 1 ELSE 0 END) AS count_recd, 
SUM(CASE WHEN c.item_received_date IS NOT NULL THEN 1 ELSE 0 END)*100/COUNT(*) AS percent_recd 
FROM cases c WHERE (c.created_date >= '2017-05-01 00:00:00' AND c.created_date <= '2017-05-31 23:59:59') 
GROUP BY c.case_mgr_first ORDER BY c.case_mgr_first ASC 

そして、それは私にresult-

+----------------+-----------+------------+--------------+ 
| case_mgr_first | count_new | count_recd | percent_recd | 
+----------------+-----------+------------+--------------+ 
| NULL   |  137 |   62 | 45.26  | 
| barney   |  84 |   44 | 52.38  | 
| betty   |  72 |   37 | 51.39  | 
| fred   |  116 |   47 | 40.52  | 
| wilma   |  61 |   19 | 31.15  | 
+----------------+-----------+------------+--------------+ 

を与える(そのbamm-bammは、最初の結果ではなく、2番目の結果に表示され、2番目の結果でNULLのエントリがあることに注意してください。 )

私は(私は読みやすいようcount_newとcount_recdを削除)このようになります組み合わせた結果をしたいと思います -

+-----------+-----------------------+-----------------------------+ 
| user  | percent_recd_case_mgr | percent_recd_case_mgr_first | 
+-----------+-----------------------+-----------------------------+ 
| NULL  | NULL     | 45.26      | 
| bamm-bamm | 40.00     | NULL      | 
| barney | 40.95     | 52.38      | 
| betty  | 50.00     | 51.39      | 
| fred  | 38.85     | 40.52      | 
| wilma  | 57.73     | 31.15      | 
+-----------+-----------------------+-----------------------------+ 

私はサブクエリを使用してこれらを結合することでかなり近づきましたが、ユーザーは正しく結合されていますが、LEFT JOINでは最初のクエリには表示されない2番目のクエリの結果が失われています。 userはNULLで、右のジョインでは、最初のものから2番目のものにない結果が失われています。また、クエリの継続時間はサブクエリの合計にすぎないと思われますが、これは改善できないかもしれませんが、わかりません。ここで

私はここに

SELECT * FROM 
(
SELECT c.case_mgr AS case_mgr, SUM(CASE WHEN c.item_received_date IS NOT NULL THEN 1 ELSE 0 END)*100/COUNT(*) AS percent_recd 
FROM cases c WHERE (c.created_date >= '2017-05-01 00:00:00' AND c.created_date <= '2017-05-31 23:59:59') 
GROUP BY c.case_mgr 
) a 
LEFT JOIN 
(
SELECT c.case_mgr_first AS case_mgr_first, SUM(CASE WHEN c.item_received_date IS NOT NULL THEN 1 ELSE 0 END)*100/COUNT(*) AS percent_recd 
FROM cases c WHERE (c.created_date >= '2017-05-01 00:00:00' AND c.created_date <= '2017-05-31 23:59:59') 
GROUP BY c.case_mgr_first 
) b 
ON a.case_mgr = b.case_mgr_first 
ORDER BY a.case_mgr ASC 

をtried-そしてクエリがresult-

+-----------+-----------------------+----------------+-----------------------------+ 
| case_mgr | percent_recd_case_mgr | case_mgr_first | percent_recd_case_mgr_first | 
+-----------+-----------------------+----------------+-----------------------------+ 
| bamm-bamm | 50.00     | NULL   | NULL      | 
| barney | 40.95     | barney   | 52.38      | 
| betty  | 50.00     | betty   | 51.39      | 
| fred  | 38.85     | fred   | 40.52      | 
| wilma  | 57.73     | wilma   | 31.15      | 
+-----------+-----------------------+----------------+-----------------------------+ 

は、私は2つのクエリでこれを行うと、コードでそれらを組み合わせることができますが、それらを持っていいだろう特にパフォーマンスが何らかの形で改善できるかどうかを確認する必要があります。

もう少し読んで、私はこれが他のSQLのFULL OUTER JOINのようであり、MySQLには存在しないと理解しています。 LEFT JOINとRIGHT JOINのUNIONでMySQLでエミュレートされています。さて、私はそれを試してみましたが、うまくいきましたが、それは92秒かかります(そして、最初に述べた "who_last_called"のような別のフィールドを追加するとかなり悪くなります)。元の2つのクエリはそれぞれ約0.22秒かかっていました。最初に試行されたJOINは0.5秒かかりました。 "case_mgr"フィールドにはインデックスがありますが、 "case_mgr_first"ではありません。

ご協力いただきありがとうございます。より良い方法があるのでしょうか、それとも個々のクエリをスティックしてコードにまとめるべきでしょうか?

+0

参照してください。私は非常に単純なSQLクエリであるように思える](http://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to -be-a-very-simple-sql-query) – Strawberry

+0

@Strawberryこの質問のために多くの検索を行い、sqlfiddleを使用している人もいました。私はjsfiddleを知っていましたが、sqlfiddleが存在することを認識しませんでした。だから私はこの質問を書いている間、例を出そうとしてみたが、サイトはうまくいかなかった。ブラウザごとにいくつかのリロードがあっても完全に空白だった。ちょうど今チェックすると、感謝して再び働くように見えます。 – mikato

+0

Sqlfiddleは使いやすいですが、私はrextesterを好む。しかし、いずれにせよ、それはリンクされた答えの中で最も重要ではない部分です。 – Strawberry

答えて

1

私はあなたが選択することをサブの上に再びあなたは、サブ選択し、グループUNIONを行うソリューションをでっち上げることができると思いますが、かなりあること、それはつもりはありません:[なぜ私はMCVEを提供する必要があり

SELECT tmp.mgr, 
    SUM(tmp.percent_recd_case_mgr) AS percent_recd_case_mgr, 
    SUM(tmp.percent_recd_case_mgr_first) AS percent_recd_case_mgr 
FROM ((
    -- this the first part will basically contain the case_mgr data 
    SELECT 
    c.case_mgr AS mgr, 
    SUM(
     CASE WHEN c.item_received_date IS NOT NULL THEN 1 ELSE 0 END 
    )*100/COUNT(*) AS percent_recd_case_mgr, 
    0 AS percent_recd_case_mgr_first -- 0 as third column 
    FROM cases c 
    WHERE 
    c.created_date >= '2017-05-01 00:00:00' 
    AND c.created_date <= '2017-05-31 23:59:59' 
    GROUP BY c.case_mgr ORDER BY c.case_mgr ASC 
) UNION (
    -- And the second part contains the case_mgr_first data 
    SELECT 
    c.case_mgr_first AS mgr, 
    0 AS percent_recd_case_mgr, -- 0 as second column 
    SUM(
     CASE WHEN c.item_received_date IS NOT NULL THEN 1 ELSE 0 END 
    )*100/COUNT(*) AS percent_recd_case_mgr_first 
    FROM cases c 
    WHERE 
    c.created_date >= '2017-05-01 00:00:00' 
    AND c.created_date <= '2017-05-31 23:59:59' 
    GROUP BY c.case_mgr_first ORDER BY c.case_mgr_first ASC 
)) AS tmp -- together both parts form a temp table and we sum again 
      -- over all records 
GROUP BY tmp.mgr 
ORDER BY tmp.mgr ASC; 
+0

これはうまくいくようです!私はそれがどのように機能するか見る。これは正しい出力を得て、単一のJOINを持つクエリと同じ時間に実行されます。別のフィールドに追加する場合は、UNIONチェーン内の別のブロックと追加の列になります。たぶんかわいらしくはないが、時間と厄介レベルの両方でFULL OUTER JOINをエミュレートする他の方法よりもはるかに優れているかもしれません:) 私は3行目の最後に "_first"を追加するように答えを編集しました。 また、元のクエリの最後に回答が追加され、出力を表示するrextester.comの例があります。 http://rextester.com/MDS93276 – mikato

関連する問題