3

私は何日も次の問題を抱えています。何とか解決できましたが、気になるのはパフォーマンスです。

基本的に、人のテーブルが 1 つと、 への参照を含む 2 つのテーブル (debtおよびwealth) がありますpersondebt/wealthテーブルには、同じ を参照する複数の行を含めることができますpersonID

私は、負債と富の合計を独自の列としてリストしたすべての人を単純に表示する結果が必要です。

まず、私が持っているテーブルを表してみましょう:

テーブル「人」:

| ID | name    |
|----|---------|
|  1 | Adam    |
|  2 | Berg    |
|  3 | Carl    |
|  4 | David   |

テーブル「富」:

| ID | personID | value    |
|----|----------|----------|
|  1 |  1       |  100     |
|  2 |  1       |  2000    |
|  3 |  2       |  30000   |
|  4 |  3       |  400000  |
|  5 |  3       |  5000000 |

テーブル「負債」:

| ID | personID | value    |
|----|----------|----------|
|  1 |  1       |  100     |
|  2 |  1       |  2000    |
|  3 |  2       |  30000   |
|  4 |  2       |  400000  |
|  5 |  3       |  5000000 |

期待される結果:

| personID | debtSum | wealthSum |
|----------|---------|-----------|
|  1       |    2100 |      2100 |
|  2       |   30000 |    430000 |
|  3       | 5400000 |   5000000 |
|  4       |  (null) |    (null) |

私の解決策:

SQL Fiddle

SELECT SQL_NO_CACHE p.ID, debtSum, wealthSum
FROM person AS p
LEFT JOIN (SELECT personID, SUM(value) AS debtSum FROM debt GROUP BY personID) AS d ON d.personID = p.ID
LEFT JOIN (SELECT personID, SUM(value) AS wealthSum FROM wealth GROUP BY personID) AS w ON w.personID = p.ID

このクエリは正しいデータを返しますが、前述のとおり、パフォーマンスが心配です。たとえば、存在しない人 (たとえば、personID = 5) の債務テーブル内に何千もの行を追加した場合、クエリの実行に時間がかかります。結果には必要ありませんが、その人のすべてのデータも合計していると思いますか?

私は SQL Server 2008 を使用していますが、SQL FiddleMySQL を使用しています (違いがある場合)。

クエリのパフォーマンスを向上させる方法に関するヒントをいただければ幸いです。私はアイデアが不足しています。

4

1 に答える 1

1

さて、これが私が行う方法ですが、適切なインデックスはクエリ構造よりもパフォーマンスに大きな影響を与えると思います:

投稿コメントを編集:

SELECT ID, SUM(debtSum) AS debtSum, SUM(wealthSum) AS wealthSum
FROM (
SELECT p.ID, d.value AS debtSum, NULL AS wealthSum
FROM person AS p
LEFT JOIN debt d ON d.personID = p.ID
UNION ALL
SELECT p.ID, NULL AS debtSum, w.Value AS wealthSum
FROM person AS p
LEFT JOIN wealth w ON w.personID = p.ID
) t
GROUP BY t.ID

Person.Id、Debt.PersonID、および Wealth.PersonID にインデックスが必要です。

于 2015-06-03T19:19:33.980 に答える