2009-08-05 6 views
0

I表は、次のフィールドで登録を求めている:不要なSQLサブセレクトを取り除く最も良い方法は?

  • イド
  • DateStarted(nullでない)
  • DateCompleted(NULL可能)

Iは、数を示す棒グラフを有します日付によって開始され完了した登録の数。 私のクエリは次のようになります。

DateStarted StartCount CompleteCount 
2009-08-01 1033  903 
2009-08-02 540   498 

クエリはちょうどそれらのコードのにおいの問題の一つでありますように見えるテーブルを返し

; 
WITH Initial(DateStarted, StartCount) 
as (
    select Datestarted, COUNT(*) 
    FROM Registrations 
    GROUP BY DateStarted  
) 
select I.DateStarted, I.StartCount, COUNT(DISTINCT R.RegistrationId) as CompleteCount 
    from Initial I 
     inner join Registrations R 
      ON (I.DateStarted = R.DateCompleted) 
    GROUP BY I.DateStarted, I.StartCount 

。これを行う良い方法は何ですか?

+0

はそれがDateCompletedは登録が存在しているレコードがないする日付であることは可能ですか?例えば07/31のレコードが開始日として記録されていないが、その日付に登録が完了したレコードはありますか? – shahkalpesh

+0

私が正しく理解している場合、「CompleteCount」列は、過去に開始されたデータの数ではなく、日付で開始された登録の数(「StartCount」列)もその日に終了しました。これが正しくない場合は、明確にしてください。 --thnx – RBarryYoung

+0

(開始日と終了日は同じです) – RBarryYoung

答えて

1

編集:なぜ以下のようなことはありませんか? NULLの代わりにカウントをゼロにしたい場合は、最後のselectステートメントのカウントの周りにcoalesce()ステートメントをスローすることができます。その日付に登録が開始されていなくても、登録が完了した(または以下の例では終了した)日付も含まれます。


私は次の表の構造(大まかに)を想定しています。

create table temp 
(
    id int, 
    start_date datetime, 
    end_date datetime 
) 

insert into temp values (1, '8/1/2009', '8/1/2009') 
insert into temp values (2, '8/1/2009', '8/2/2009') 
insert into temp values (3, '8/1/2009', null) 
insert into temp values (4, '8/2/2009', '8/2/2009') 
insert into temp values (5, '8/2/2009', '8/3/2009') 
insert into temp values (6, '8/2/2009', '8/4/2009') 
insert into temp values (7, '8/4/2009', null) 

次に、あなたが望むものを得るために次のことができます。

with start_helper as 
(
    select start_date, count(*) as count from temp group by start_date 
), 

end_helper as 
(
    select end_date, count(*) as count from temp group by end_date 
) 

select coalesce(a.start_date, b.end_date) as date, a.count as start_count, b.count as end_count 
from start_helper a full outer join end_helper b on a.start_date = b.end_date 
where coalesce(a.start_date, b.end_date) is not null 

私は完全外部レコードが昨日スタートしたが、あなたの結果から、一日を失うことになるので、私たちは今日、新しいレコードを開始していないことが、今日を完了することができますので、必要な参加と思うだろう。

+0

それはうまくいくようですが、最終的に3つの選択クエリを実行しますために。私は先に進み、あなたを上げた。ありがとう。 – NotMe

0

問題はありません。私は使用されている共通のテーブル式を参照してください。


あなたはテーブルのDDLを提供していないので、これを再現しようとはしません。しかし、私はあなたが直接Initialの使用のためにSELECTを代用することができるかもしれないと思います。

1

オフの手、私は、これはそれをしないと思う:

SELECT 
    DateStarted 
    , COUNT(*) as StartCount 
    , SUM(CASE 
     WHEN DateCompleted = DateStated THEN 1 
     ELSE 0 END 
     ) as CompleteCount 

FROM Registration 

GROUP BY DateStarted 

OK、どうやら私は間違って前に要件を持っていました。 CompleteCountsは、開始日とは無関係であることを考えると、これは、私はそれを行うだろうかです:実際にあなたが持っていたものにかなり近いです

;WITH StartDays AS 
(
    SELECT DateStarted 
    , Count(*) AS CompleteCount 
    FROM Registration 
    GROUP BY DateStarted 
) 
, CompleteDays AS 
(
    SELECT DateCompleted 
    , Count(*) AS StartCount 
    FROM Registration 
    GROUP BY DateCompleted 
) 
SELECT 
    DateStarted 
    , COALESCE(StartCount, 0) AS StartCount 
    , COALESCE(CompleteCount, 0) AS CompleteCount 

FROM StartDays 
FULL OUTER JOIN CompleteDays ON DateStarted = DateCompleted 

+0

いいですね。でも、違った数字が出ます。特に、CompleteCountは間違っています。それは数百にも満たない。 – NotMe

+0

最後のレコードで間違っています。 – NotMe

+0

問題を示すデータがありますか? AFAIKので、これはあなたの質問への技術的に正解であり、私のテストのすべてが私のコードの正解を返します。したがって、あいまいな境界条件があり、暗黙のうちにコードによって一方的に処理され、異なる結果が得られると結論づけなければなりません。 – RBarryYoung

0

私は次はあなたが持っているものと機能は同じであると考えている:

select DS.DateStarted 
    , count(distinct DS.RegistrationId) as StartCount 
    , count(distinct DC.RegistrationId) as CompleteCount 
from Registrations DS 
inner join Registrations DC on DS.DateStarted = DC.DateCompleted 
group by Ds.DateStarted 

私は結果にDateStarted列の名前で混乱ビットです。それはちょうどいくつかの事が始まっていくつかのことが終わった日であるように見えます。カウントは、その日に開始され完了した番号または登録です。

内部結合は、0の開始または0の完了のいずれかの日付をスローしています。すべて取得するには:あなたがDateStartedもDateCompletedでもない日を含めたい場合

select coalesce(DS.DateStarted, DC.DateCompleted) as "Date" 
    , count(distinct DS.RegistrationId) as StartCount 
    , count(distinct DC.RegistrationId) as CompleteCount 
from Registrations DS 
full outer join Registrations DC on DS.DateStarted = DC.DateCompleted 
group by Ds.DateStarted, DC.DateCompleted 

は、0と0のカウントで、あなたは、日付のソースが必要になりますし、私は2つの相関関係を使用して明確だと思いますSELECT句のサブクエリの代わりに参加し、個別のカウント:

select DateSource."Date" 
    , (select count(*) 
     from Registrations 
     where DateStarted = DateSource."Date") as StartCount 
    , (select count (*) 
     from Registrations 
     where DateCompleted = DateSource."Datge") as CompleteCount 
from DateSource -- implementation of date source left as exercise 
where DateSource.Date between @LowDate and @HighDate