5

次のクエリを使用して、クライアント用、作業時間用、経費用の 3 つのテーブルからクライアントの作業時間と経費をグループ化しています。

SELECT  a.*,
        COALESCE(b.totalCount, 0) AS CountWork,
        COALESCE(b.totalAmount, 0) AS WorkTotal,
        COALESCE(c.totalCount, 0) AS CountExpense,
        COALESCE(c.totalAmount, 0) AS ExpenseTotal
FROM    clients A
        LEFT JOIN
        (
            SELECT  Client, 
                    COUNT(*) totalCount,
                    SUM(Amount) totalAmount
            FROM    work_times
            WHERE   DATE BETWEEN '2013-01-01' AND '2013-02-01'
            GROUP   BY Client
        ) b ON a.Client = b.Client
        LEFT JOIN
        (
            SELECT  Client, 
                    COUNT(*) totalCount,
                    SUM(Amount) totalAmount
            FROM    expenses
            WHERE   DATE BETWEEN '2013-01-01' AND '2013-02-01'
            GROUP   BY Client
        ) c ON a.Client = c.Client
WHERE   b.Client IS NOT NULL OR
        c.Client IS NOT NULL

ここでフィドルで動作するクエリを確認できます。

このクエリを修正して、月ごとにクライアントごとにソートされた各クライアントの行があるようにしようとしています。私は次の修正されたクエリでそうしようとしています:

SELECT  a.*,
        COALESCE(b.totalCount, 0) AS CountWork,
        COALESCE(b.totalAmount, 0) AS WorkTotal,
        COALESCE(c.totalCount, 0) AS CountExpense,
        COALESCE(c.totalAmount, 0) AS ExpenseTotal
FROM    clients A
        LEFT JOIN
        (
            SELECT  Client, 
                    COUNT(*) totalCount,
                    SUM(Amount) totalAmount,
                    SUBSTR(Date, 1, 7) as Month
            FROM    work_times
            GROUP   BY Month,Client
            ORDER BY Month
        ) b ON a.Client = b.Client
        LEFT JOIN
        (
            SELECT  Client, 
                    COUNT(*) totalCount,
                    SUM(Amount) totalAmount,
                    SUBSTR(Date, 1, 7) as Month
            FROM    expenses
            GROUP   BY Month,Client
            ORDER BY Month,Client
        ) c ON a.Client = c.Client
WHERE   b.Client IS NOT NULL OR
        c.Client IS NOT NULL

修正されたクエリの動作はこちらで確認できます。

しかし、それはまったく正しく機能していません。2013 年 1 月に作業時間があり、2013 年 2 月に出費があるにもかかわらず、クライアント B には 1 行しか返されず (したがって 2 行あるはずです)、月ではなくクライアント別に行が並べられているように見えます。2番目のフィドルの例では、クエリを修正して目的の出力を取得する方法を誰かが提案できますか:

╔════════╦═══════════╦═══════════╦══════════════╦══════════════╗
║ CLIENT ║ COUNTWORK ║ WORKTOTAL ║ COUNTEXPENSE ║ EXPENSETOTAL ║
╠════════╬═══════════╬═══════════╬══════════════╬══════════════╣
║ A      ║         1 ║        10 ║            1 ║           10 ║
║ B      ║         1 ║        20 ║            0 ║            0 ║
║ A      ║         1 ║        15 ║            0 ║            0 ║
║ B      ║         0 ║        0  ║            1 ║           10 ║
║ C      ║         1 ║        10 ║            0 ║            0 ║
╚════════╩═══════════╩═══════════╩══════════════╩══════════════╝
4

2 に答える 2

2

要件に欠けているものがない限り、クライアントと日付のリストを取得し、それをサブクエリに結合する必要があります。したがって、クエリは次のようになります。

SELECT a.*,
  COALESCE(b.totalCount, 0) AS CountWork,
  COALESCE(b.totalAmount, 0) AS WorkTotal,
  COALESCE(c.totalCount, 0) AS CountExpense,
  COALESCE(c.totalAmount, 0) AS ExpenseTotal
FROM 
(
  select distinct c.Client, d.Month
  from clients c
  cross join
  (
    select SUBSTR(Date, 1, 7) as Month
    from work_times
    union 
    select SUBSTR(Date, 1, 7) as Month
    from expenses
  ) d
) A
LEFT JOIN
(
  SELECT  Client, 
    COUNT(*) totalCount,
    SUM(Amount) totalAmount,
    SUBSTR(Date, 1, 7) as Month
  FROM    work_times
  GROUP   BY Month,Client
  ORDER BY Month,Client
) b 
  ON a.Client = b.Client
  and a.month = b.month
LEFT JOIN
(
  SELECT  Client, 
    COUNT(*) totalCount,
    SUM(Amount) totalAmount,
    SUBSTR(Date, 1, 7) as Month
  FROM    expenses
  GROUP   BY Month,Client
  ORDER BY Month,Client
) c 
  ON a.Client = c.Client
  and a.month = c.month
WHERE   b.Client IS NOT NULL OR
        c.Client IS NOT NULL
order by a.month, a.client

SQL Fiddle with Demoを参照してください。

結果は次のとおりです。

| CLIENT |   MONTH | COUNTWORK | WORKTOTAL | COUNTEXPENSE | EXPENSETOTAL |
--------------------------------------------------------------------------
|      A | 2013-01 |         1 |        10 |            1 |           10 |
|      B | 2013-01 |         1 |        20 |            0 |            0 |
|      A | 2013-02 |         1 |        15 |            0 |            0 |
|      B | 2013-02 |         0 |         0 |            1 |           20 |
|      C | 2013-02 |         1 |        10 |            0 |            0 |
于 2013-02-24T18:30:54.717 に答える
0

サブクエリで order by を実行しても問題ありません。外側のクエリが結果を並べ替える可能性がある (必要になる可能性がある) からです。外側のクエリに order by を追加したいとします。

問題は、B テーブルの月とクライアントで注文し、C テーブルの月とクライアントで注文しようとしていることです。B.month、B.client、C.monthの順番を定義し、外側のクエリのorder byに入れる必要があります。

ところで、C テーブルのサブクエリで月ごとにグループ化するだけの場合、クライアントは意味がありません。DB2 などの一部のデータベースでは、グループ化されていない場合、集計されていないフィールドを select に入れることができません。

于 2013-02-24T17:54:40.883 に答える