5

基本的に次のことを行う単純なレポート送信フレームワークがあります。SELECTクエリを実行し、結果に基づいてテキスト形式のテーブルを作成し、電子メールを送信し、UPDATEクエリを実行します。

このシステムは、すべての操作がハードコーディングされた古いシステムを一般化したものです。しかし、私がやりたいことのすべてのロジックをSELECTクエリにプッシュする際に、問題が発生しました。

以前は、次のように言うことで、テキストテーブルのほとんどの情報を取得できました。

SELECT Name, Address FROM Databas.Tabl WHERE Status='URGENT';

次に、電子メール用に追加の番号が必要になった場合は、次の手順も実行します。

SELECT COUNT(*) FROM Databas.Tabl WHERE Status='URGENT' AND TimeLogged='Noon';

今では、複数のSELECTクエリの贅沢はもうありません。私がやりたいことは次のようなものです:

SELECT Tabl.Name, Tabl.Address, COUNT(Results.UID) AS Totals
FROM Databas.Tabl
LEFT JOIN Databas.Tabl Results
    ON Tabl.UID = Results.UID
    AND Results.TimeLogged='Noon'
WHERE Status='URGENT';

これは、少なくとも私の頭の中では、選択され、条件付きのすべての行の総数を取得することを意味します。

ただし、実際には、これにより、「1140-GROUP BYがない場合、GROUP列がない場合のGROUP列の混合は不正です」というエラーが発生します。問題は、GROUPBYを使用したくないということです。このCOUNTで、TimeLogged='Noon'でSELECTが検出した結果の数を冗長に繰り返す必要があります。または、AND句を削除して、SELECTステートメントの結果の列として、そのSELECTステートメントが検出した結果の数を含めたいと思います。

GROUP BYは答えではありません。これは、ある列で同じ値を持つ行のみのCOUNTを取得するためです。そして、COUNTは頭に浮かぶことですが、これを実行する方法ではないかもしれません。FOUND_ROWS()は、セカンダリクエリの一部である必要があるため、このトリックを実行しません。取得するのは1つだけであり(さらに、LIMITは含まれていません)、ROW_COUNT()はSELECTステートメントであるため、機能しないようです。

完全に間違った角度からアプローチしているのかもしれません。しかし、私がやりたいのは、SELECTクエリの結果に関するCOUNTタイプの情報と、SELECTクエリが返した他のすべての情報を1つのクエリで取得することです。

===これが私がこれまでに得たものです===

SELECT Tabl.Name, Tabl.Address, Results.Totals
FROM Databas.Tabl
LEFT JOIN (SELECT COUNT(*) AS Totals, 0 AS Bonus
           FROM Databas.Tabl
           WHERE TimeLogged='Noon'
           GROUP BY NULL) Results
     ON 0 = Results.Bonus
WHERE Status='URGENT';

これは、私が最初は避けたいと思っていたサブSELECTを使用しますが、今では希望が愚かだった可能性があることに気づきました。さらに、COUNT条件はすべて1つのテーブルにあるため、COUNTing SELECTサブクエリはメインクエリよりもコストがかからないようですが、実際に使用しているSELECTは、派生情報のために複数の異なるテーブルに結合する必要があります。

重要な認識は、GROUP BY NULLを使用できることです。これにより、COUNT(*)が実際にすべてをキャッチするように単一の結果が返され、両方のテーブルで0のボーナス列を偽造するだけでこの列との相関を強制できます。

これが私が使用する解決策のように見えますが、実際には明日まで答えとして受け入れることはできません。すべての助けをありがとう。

4

5 に答える 5

14
SELECT Tabl.Name, Tabl.Address, Results.Totals
FROM Databas.Tabl
LEFT JOIN (SELECT COUNT(*) AS Totals, 0 AS Bonus
           FROM Databas.Tabl
           WHERE TimeLogged='Noon'
           GROUP BY NULL) Results
     ON 0 = Results.Bonus
WHERE Status='URGENT';

複数の回答から生まれたアイデアのおかげでこれを理解しましたが、実際には誰の直接の結果でもありません。なぜこれが必要なのかは元の投稿の編集で説明されていますが、他の誰かがこのばかげた種類の操作を実行したい場合に備えて、適切な答えで質問を解決できるようにしたかったのです。助けてくれたすべての人に感謝します。

于 2010-09-30T15:58:03.750 に答える
2

これはあなたが必要とすることをしますか?

SELECT   Tabl.Name                   ,
         Tabl.Address                ,
         COUNT(Results.UID) AS GrandTotal,
         COUNT(CASE WHEN Results.TimeLogged='Noon' THEN 1 END) AS NoonTotal
FROM     Databas.Tabl
         LEFT JOIN Databas.Tabl Results
         ON       Tabl.UID = Results.UID
WHERE    Status            ='URGENT'
GROUP BY Tabl.Name,
         Tabl.Address
WITH ROLLUP;
于 2010-09-29T23:21:26.823 に答える
2

代わりに、おそらくユニオンを行うことができます。元のクエリに列を追加して0を選択してから、2番目のクエリでUNIONを選択すると、単一の列が返されます。そのためには、2番目のクエリでも最初のクエリと一致する空のフィールドを選択する必要があります。

SELECT Cnt = 0, Name, Address FROM Databas.Tabl WHERE Status='URGENT'
UNION ALL
SELECT COUNT(*) as Cnt, Name='', Address='' FROM Databas.Tabl WHERE Status='URGENT' AND TimeLogged='Noon';

ちょっとしたハックですが、あなたがやろうとしていることは理想的ではありません...

于 2010-09-29T23:24:41.303 に答える
0

データベースへのアクセスに使用しているAPIは、返された行数を報告できる必要があります。たとえば、perlを実行している場合は、次のようにすることができます。

my $sth  = $dbh->prepare("SELECT Name, Address FROM Databas.Tabl WHERE Status='URGENT'");
my $rv   = $sth->execute();
my $rows = $sth->rows;
于 2010-09-29T23:21:36.653 に答える
0

Tabl.idでグループ化すると、結果が台無しになるとは思わない。それを試してみて、それがあなたが望むものであるかどうかを確認してください。

于 2010-09-29T23:25:18.440 に答える