3

レポート用にこのクエリを書きました。しかし、私は元々、すべてのサブクエリで日付範囲フィルターなしで書いていました。しかし、それはうまくいきませんでした。そのため、各サブクエリに追加しました。それはうまくいきましたが、毎回それを繰り返さなければならないのは本当に好きではありません.同じことをより簡単にする構文はありますか?

 SELECT Count(r.id)                       AS cnt_total,
   (SELECT Count(r1.entity_id)
    FROM   auto_reminders_members r1
    WHERE  r1.reminder_id = r.reminder_id
           AND r1.date_last_reminder BETWEEN CONVERT(DATETIME, '03/28/2013',
                                             101)
                                             AND
               CONVERT(DATETIME,
               '03/28/2013' + ' 23:59:59.997 ', 101)
           AND r1.action = 'notnow') AS cnt_notnow,
   (SELECT Count(r1.entity_id)
    FROM   auto_reminders_members r1
    WHERE  r1.reminder_id = r.reminder_id
           AND r1.date_last_reminder BETWEEN CONVERT(DATETIME, '03/28/2013',
                                             101)
                                             AND
               CONVERT(DATETIME,
               '03/28/2013' + ' 23:59:59.997 ', 101)
           AND r1.action = 'insert') AS cnt_insert,
   (SELECT Count(r1.entity_id)
    FROM   auto_reminders_members r1
    WHERE  r1.reminder_id = r.reminder_id
           AND r1.date_last_reminder BETWEEN CONVERT(DATETIME, '03/28/2013',
                                             101)
                                             AND
               CONVERT(DATETIME,
               '03/28/2013' + ' 23:59:59.997 ', 101)
           AND r1.action = 'update') AS cnt_update,
   (SELECT Count(r1.entity_id)
    FROM   auto_reminders_members r1
    WHERE  r1.reminder_id = r.reminder_id
           AND r1.date_last_reminder BETWEEN CONVERT(DATETIME, '03/28/2013',
                                             101)
                                             AND
               CONVERT(DATETIME,
               '03/28/2013' + ' 23:59:59.997 ', 101)
           AND r1.action = 'verify') AS cnt_verify
FROM   auto_reminders_members r
WHERE  r.reminder_id = 1
       AND r.date_last_reminder BETWEEN CONVERT(DATETIME, '03/28/2013', 101) AND
                                            CONVERT(DATETIME,
                                            '03/28/2013' + ' 23:59:59.997 ', 101
                                            )
GROUP  BY r.reminder_id  
4

6 に答える 6

11

これは、すべてのサブクエリなしでそれを行う方法です

SELECT  Count(r.id) AS cnt_total,
        sum(case when r.action = 'notnow' then 1 else 0 end) as 'cnt_notnow',
        sum(case when r.action = 'insert' then 1 else 0 end) as 'cnt_insert',
        sum(case when r.action = 'update' then 1 else 0 end) as 'cnt_update',
        sum(case when r.action = 'verify' then 1 else 0 end) as 'cnt_verify'        
FROM    auto_reminders_members r

WHERE  r.reminder_id = 1
       AND CONVERT(DATE, r.date_last_reminder) = '20130328'

また、クエリを少しクリーンアップし、これが常に 1 になるように group by を削除し、日付の比較を変更して、ロジック間の乱雑さを使用しないようにしました (コメントについて Aaron に感謝します)。

于 2013-03-28T18:29:21.043 に答える
2

GROUPING SETSとを使用する方法を次に示しPIVOTますが、これは使用しているバージョンによって異なります。

DECLARE @reminder_id INT, @date DATE;

SELECT @reminder_id = 1, @date = '20130328';

;WITH x AS 
(
  SELECT [action] = COALESCE([action],'Total'), c2 = COUNT(*)
    FROM dbo.auto_reminders_members
    WHERE reminder_id = @reminder_id
    AND CONVERT(DATE, date_last_reminder) = @date
    GROUP BY GROUPING SETS(([action]), ())
)
SELECT reminder_id = @reminder_id, * FROM x 
PIVOT 
(
  MAX([c2]) FOR [action] IN ([Total],[notnow],[insert],[update],[verify])
) AS p;

2005 年の場合、GROUPING SETS行を古いスタイルの構文に置き換えることができます。

    GROUP BY [action] WITH ROLLUP

BETWEEN私は、人々が大目に見たり、この魔法の「一日の終わり」のものをやめてくれることを本当に願っています. 丸一日必要な場合は、WHERE 句を次のいずれかにする必要があります。

WHERE CONVERT(DATE, r.date_last_reminder) = '20130328'

または、2005 を使用している場合:

WHERE r.date_last_reminder >= '20130328'
  AND r.date_last_reminder <  '20130329'

ここでいくつかの重要なポイントがあります。主23:59:59.997に、基になるデータ型に応じてデータが切り上げられたり欠落したりする可能性があること、日時の値を文字列に変換してクエリを実行する必要がないこと、および地域の形式などm/d/yはさまざまな理由があります (たとえば、クエリが03/08/20133 月 8 日以降か 8 月 3 日以降かわかりません)。

これらの記事を読んでください:

entity_idやなどの列名に予約語/キーワードを使用することにも注意する必要がありますaction

于 2013-03-28T18:36:32.280 に答える
0
select convert(nvarchar(10),warnt.created_dt,120) 'Date',loc.loc_name 'Location',--   
loctype.LocationTypeDesc,
 (select SUM(stk.sel_price) from tbl_mst_stock as stk 
inner join tbl_gen_warranty as wrn on stk.Stock_ID=wrn.Stock_Id
inner join tbl_mst_model as mdl on mdl.Model_ID=wrn.model_id
where wrn.mobile_type like 'SL')'Selleing Price',
(Select COUNT(stk.stk_code) from tbl_mst_stock as stk 
inner join tbl_gen_warranty as warn on stk.Stock_ID=warn.Stock_Id
inner join tbl_mst_model mdl on mdl.Model_ID=warn.model_id
    where warn.mobile_type like 'SL') 'Stock count'
From tbl_mst_location as loc 
inner join tbl_mst_location_types loctype on loc.LocationTypeID=loctype.LocationTypeID
inner join tbl_gen_warranty as warnt on loc.Location_ID=warnt.Location_id
Where  loctype.LocationTypeID=1 and loctype.group_id=1 
and (CONVERT(nvarchar(10),warnt.created_dt,120) 
Between CONVERT(nvarchar(10),'2013-01-01',120) and convert(nvarchar(10),'2013-07-09'))
Group by loc.loc_name,loctype.LocationTypeDesc,warnt.created_dt,loctype.LocationTypeID
于 2013-07-14T08:27:10.627 に答える
0

あなたはこのようなことをすることができるかもしれません

SELECT Count(r.id) AS cnt_total,
  SUM(CASE WHEN r1.action = 'notnow') THEN 1 ELSE 0 END) AS cnt_notnow,
  SUM(CASE WHEN r1.action = 'insert') THEN 1 ELSE 0 END) AS cnt_insert,
  SUM(CASE WHEN r1.action = 'update') THEN 1 ELSE 0 END) AS cnt_update,
  SUM(CASE WHEN r1.action = 'verify') THEN 1 ELSE 0 END) AS cnt_verify,

FROM   auto_reminders_members r
WHERE  r.reminder_id = 1
       AND r.date_last_reminder BETWEEN CONVERT(DATETIME, '03/28/2013', 101) AND
                                            CONVERT(DATETIME,
                                            '03/28/2013' + ' 23:59:59.997 ', 101
                                            )
GROUP  BY r.reminder_id
于 2013-03-28T18:29:33.250 に答える
0

これを試して:

select 
    reminder_id,
    count(1) as Total,
    sum(case when  r1.action = 'notnow' then 1 else 0 end) as cnt_notnow,
    sum(case when  r1.action = 'insert' then 1 else 0 end) as cnt_insert,
    sum(case when  r1.action = 'update' then 1 else 0 end) as cnt_update,
    sum(case when  r1.action = 'verify' then 1 else 0 end) as cnt_verify
from auto_reminders_members r
WHERE  r.reminder_id = 1
   AND r.date_last_reminder BETWEEN CONVERT(DATETIME, '03/28/2013', 101) AND
                                        CONVERT(DATETIME,
                                        '03/28/2013' + ' 23:59:59.997 ', 101
                                        )
GROUP  BY r.reminder_id 
于 2013-03-28T18:30:37.930 に答える
0

1 つの代替ソリューションが見つかりました:

 SELECT Sum(1)   AS cnt_total,
   Sum(CASE
         WHEN r.action = 'notnow' THEN 1
         ELSE 0
       END) AS cnt_notnow,
   Sum(CASE
         WHEN r.action = 'insert' THEN 1
         ELSE 0
       END) AS cnt_insert,
   Sum(CASE
         WHEN r.action = 'update' THEN 1
         ELSE 0
       END) AS cnt_update,
   Sum(CASE
         WHEN r.action = 'verify' THEN 1
         ELSE 0
       END) AS cnt_verify

FROM auto_reminders_members r WHERE r.reminder_id = 1 AND r.date_last_reminder BETWEEN CONVERT(DATETIME, '03/28/2013', 101) AND CONVERT(DATETIME, '03/28/2013' + ' 23:59:59.997 ', 101 )

于 2013-03-28T18:31:24.187 に答える