2017-03-06 37 views
0

質問のみ金曜日の日付を取得するには:SQLクエリは、2つの日付の間

06-JAN-12 FRIDAY        
13-JAN-12 FRIDAY        
20-JAN-12 FRIDAY        
27-JAN-12 FRIDAY        
03-FEB-12 FRIDAY        
10-FEB-12 FRIDAY        
17-FEB-12 FRIDAY        
24-FEB-12 FRIDAY        
02-MAR-12 FRIDAY        
09-MAR-12 FRIDAY        
16-MAR-12 FRIDAY        
23-MAR-12 FRIDAY        
30-MAR-12 FRIDAY

訪問以上のSQLクエリ:どのように私はOracleで2つの日付の間のみ金曜日の日付を選択行う

SELECT dates,TO_CHAR(dates,'day-mon-yyyy') 
FROM 
(SELECT to_date('01-jan-12','dd-mon-yy')+rownum -1 AS dates 
    FROM addresses 
WHERE rownum <= to_date('31-jan-12','dd-mon-yy')- to_date('01-jan-12','dd-mon-yy')+1) 
WHERE upper(regexp_substr(TO_CHAR(dates,'day-mon-yy'),'([[:alpha:]])+'))=upper('FRIDAY'); 

私は出力などを必要とします:SQL Query Interview Questions

+1

[ask] – OldProgrammer

+0

あなたの質問/問題/エラーは何ですか?あなたが示したものは、日付文字列の周りに一重引用符を必要としますが、とにかく...とにかく複雑に思えますが、アドレステーブルには何が関係していますか? –

+0

Thanq u非常に、一重引用符を忘れていました。これはうまくいきました。 –

答えて

1

to_char()の最初の引数として使用した値が一重引用符で囲まれていないため、投稿したものからエラーが発生します。

select to_date(01-jan-12,'dd-mon-yy') from dual; 

ORA-00904: "JAN": invalid identifier 

何の引用符がないので、janは識別子として解釈され、何の列コールJANがあなたのアドレステーブルに(おそらく)はありません。 2桁の年を使用することも悪い習慣です。実際には古いデータから、通常はRRYYよりも使用する必要があります。月の名前もNLS設定の影響を受けますので、月の数字を名前よりも安全に使用できます。実際に名前が必要な場合は、to_char()関数に言語を制御する第3引数があります。

これは非常に複雑な方法で行いますが、十分な行を持つアドレステーブルに頼っています。小文字で曜日名をDAYの代わりにdayで指定し、大文字にしてから、最初に指定した文字列のビットを取り除きます。 - 唯一の曜日の名前を取得すると、NLSの設定は、とにかくあなたに英語の名前を与えるという前提(再び)を比較すると...不必要に複雑です。固定文字列リテラルに対してupper()を呼び出すと、あなたは既に大文字で入力できます。

あなたはこれらのいずれか、またはその他の変形を行うことができます

代わりの

WHERE upper(regexp_substr(TO_CHAR(dates,'day-mon-yy'),'([[:alpha:]])+'))=upper('FRIDAY'); 

WHERE regexp_substr(TO_CHAR(dates,'DAY-mon- 
y'),'([[:alpha:]])+')=upper('FRIDAY'); 
WHERE TO_CHAR(dates,'DAY')='FRIDAY '; 
WHERE TRIM(TO_CHAR(dates,'DAY'))=upper('FRIDAY'); 
WHERE TO_CHAR(dates,'FMDAY','NLS_DATE_LANGUAGE=ENGLISH')='FRIDAY'; 

あなたはdualテーブルに対して、階層的なクエリを使用してアドレステーブルに頼って避けることができます:

SELECT next_day(date '2012-01-01' - 1, 'FRIDAY') + (7 * (level - 1)) 
FROM dual 
CONNECT BY next_day(date '2012-01-01' - 1, 'FRIDAY') + (7 * (level - 1)) 
    <= date '2012-03-31'; 

next_dayも使用していますしかしNLSの設定に、あなたは常にセッションの日付言語を制御することができない限り、それはすべての日付を取得し、NLSに依存しない方法でそれらをフィルタリングする(少し効率的な場合)の方が安全かもしれませんので:

SELECT dates, to_char(dates, 'FMDAY') 
FROM (
    SELECT date '2012-01-01' + level - 1 AS dates 
    FROM dual 
    CONNECT BY level <= date '2012-03-31' - date '2012-01-01' 
) 
WHERE to_char(dates, 'FMDAY', 'NLS_DATE_LANGUAGE=ENGLISH') = 'FRIDAY'; 

DATES  TO_CHAR(DATES,'FMDAY')    
--------- ------------------------------------ 
06-JAN-12 FRIDAY        
13-JAN-12 FRIDAY        
20-JAN-12 FRIDAY        
27-JAN-12 FRIDAY        
03-FEB-12 FRIDAY        
10-FEB-12 FRIDAY        
17-FEB-12 FRIDAY        
24-FEB-12 FRIDAY        
02-MAR-12 FRIDAY        
09-MAR-12 FRIDAY        
16-MAR-12 FRIDAY        
23-MAR-12 FRIDAY        
30-MAR-12 FRIDAY        

13 rows selected. 

@mathguyがnext_day()は、NLSに敏感ですが、2番目の引数に式を使用することができ、コメントで指摘したように、その代わりに、あなたがこれを行うことができ日間の名をハードコーディングの:

next_day(date '2012-01-01' - 1, to_char(date '1999-12-31', 'FMDAY')) 

1999- 12-31は、金曜日であることが知られている任意の日付にすることができます。 selectリストとconnect-by節の式が異なっていても構いません(実際にはあなたと私は違うはずです):

SELECT dates, to_char(dates, 'FMDAY', 'NLS_DATE_LANGUAGE=ENGLISH') 
FROM (
    SELECT next_day(date '2012-01-01' - 1, 
    to_char(date '1999-12-31', 'FMDAY')) + (7 * (level - 1)) AS dates 
    FROM dual 
    CONNECT BY level <= 1 + (date '2012-03-31' - next_day(date '2012-01-01' - 1, 
    to_char(date '1999-12-31', 'FMDAY')))/7 
); 

これは、セッションの日付言語に関係なく、上記と同じ13行を取得します。出力をセッション言語にしたい場合は、オーバーライドする第3引数をto_char()に削除してください。

+1

'next_day()'を使った解決策がおそらく最も効率的です。それを呼び出すセッションの言語から独立させるために、金曜日であることが分かっている 'some_date'の' to_char(some_date、 'Day') 'を計算し、' next_day() 'の呼び出しでそれを使用することができます。同様の解決策は、 'connect ='で 'level 'の不等式を解くことでより効率的になります(' level <= 1 +( - )/ 7'と書く)。現在のフォームでは、各行に対して追加の算術計算が行われています。 – mathguy

+0

何らかの理由で、 'next_day()'の2番目の引数は式ではなく文字列でなければならないと思っていましたそれが真実ではないので、私はどこから得たのか分かりません。また効率を上げるために計算をRHSに移動することについて同意してください;選択リストとしてconnect-byと同じ式を使用して読みやすくすることは有益ですが、ここでの違いは重要な意味を持つ可能性があるので、この場合説得力のある議論ではありません。 –

関連する問題