0

ID、tDate、説明、キャッシュアウト、キャッシュインの列を持つ銀行取引のテーブルがあります。特に Amazon と Mazo というショップで、自分がどのようにお金を使っているかを知りたいので、次のような結果が必要です。

Month   Amazon   Mazo   Total
1       100      200    300

私はこれを試みました:

SELECT
    MONTH(tDate) AS Month,
    SUM(IF(description LIKE '%amazon%',cashOut,0)) AS Amazon,
    SUM(IF(description LIKE '%mazo%',cashOut,0)) AS Mazo,
    SUM(cashOut) AS Total
FROM `transactions` 
GROUP BY Month

ただし、次のことがわかりました。

Month   Amazon   Mazo   Total
1       100      300    300

この SQL クエリの問題は、「Amazon」トランザクションも加算されるため、「mazo」トランザクションの合計が間違っていることです。

各トランザクションが上記の SUM の 1 つだけの一部になるように (PHP などに頼ることなく)、合計するトランザクションの選択を相互に排他的またはそのようなものにしたい。(私のテーブルにはこれよりもはるかに多くのデータが含まれており、多くの検索基準があるため、検索語として「% mazo %」を使用するだけでは十分ではありません。問題の一般的な解決策が必要です。)

誰か提案がありますか?

テーブルとそのデータの詳細:

CREATE TABLE `transactions` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`tDate` date NOT NULL,
`description` varchar(200) NOT NULL,
`cashOut` decimal(10,0) NOT NULL,
`cashIn` decimal(10,0) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB 

INSERT INTO `transactions` (`id`, `tDate`, `description`, `cashOut`, `cashIn`) VALUES
(1, '2010-01-05', 'amazon', '100', '0'),
(4, '2010-01-15', 'mazo', '200', '0');
4

4 に答える 4

2

内部クエリの各行にフラグを立て、それをフィルタリングすることで、相互に排他的なグループを作成できます。

SELECT
    MONTH(tDate) AS Month,
    SUM(IF(flag = 'amazon', cashOut, 0)) AS Amazon,
    SUM(IF(flag = 'mazo', cashOut, 0)) AS Mazo,
    SUM(IF(flag = 'other', cashOut, 0)) AS Other,
    SUM(cashOut) AS Total
FROM (
    SELECT tDate, cashOut,
        CASE
            WHEN description LIKE '%amazon%' THEN 'amazon'
            WHEN description LIKE '%mazo%' THEN 'mazo'
            ELSE 'other'
        END AS flag
    FROM transactions
) x
GROUP BY Month

そうすれば、トランザクションが複数のキーワードに一致する場合でも、同じトランザクションを 2 回カウントすることはありません。クエリで同じキーワードを 2 回繰り返したくない場合、次のようなリストを使用できます。

Month   What     Sum
1       amazon   100
2       mazo     200

その後、次を使用できます。

SELECT
    MONTH(tDate) AS Month,
    flag AS What,
    SUM(cashOut) AS Total
FROM (
    SELECT tDate, cashOut,
        CASE
            WHEN description LIKE '%mazo%' THEN 'mazo'
            WHEN description LIKE '%amazon%' THEN 'amazon'
            ELSE 'other'
        END AS flag
    FROM transactions
) x
GROUP BY Month, flag
于 2011-08-27T13:24:53.477 に答える
1

を含む文字列を検索していますmazo。Mazo だけが必要な場合は、次のように変更します。

SUM(IF(description LIKE '%mazo%',cashOut,0)) AS Mazo,

SUM(IF(description = 'mazo',cashOut,0)) AS Mazo,

編集:コメントへの返信として、正規表現を使用して単語の境界[[:<:]]を検索できます:

SUM(IF(description REGEXP '[[:<:]]mazo[[:>:]]',cashOut,0)) AS Mazo,
于 2011-08-27T12:13:49.790 に答える
1
SELECT
    MONTH(tDate) AS Month,
    SUM(IF(description LIKE '%amazon%',cashOut,0)) AS Amazon,
    SUM(IF(description LIKE '%mazo%' AND description NOT LIKE '%amazon%',cashOut,0)) AS Mazo,
    SUM(cashOut) AS Total
FROM `transactions` 
GROUP BY Month
于 2011-08-27T12:39:13.170 に答える
0

をなくすだけ=ではなく、正確なテキストで使用してください。これを試して:likeIF

SELECT
    MONTH(tDate) AS Month,
    SUM((description = 'Amazon') * cashOut) AS Amazon,
    SUM((description = 'Mazo') * cashOut) AS Mazo,
    SUM(cashOut) AS Total
FROM `transactions`
GROUP BY Month
于 2011-08-27T12:18:48.140 に答える