2009-06-10 16 views
2

私はAccess 2003でこれを使用しています。これが間違っている場合は私を容赦しますが、誰かが助けてくれることを願っています。SQLを選択質問

私は、日付フィールドを表すテキストを持つ複数のレコードを持つテーブルを持っています。 「2009年6月1日には」私はテーブルからすべてのフィールドを選択する必要がありますが、各グループのために範囲にのみ6つの最古の行::同様

COUPONS.DocType, COUPONS.PayTo, COUPONS.ContactName, COUPONS.ContactNumber, 
COUPONS.DocFooter, COUPONS.PQBName, COUPONS.LetterDate, COUPONS.RetireeFirstName, 
COUPONS.RetireeLastName, COUPONS.Address1, COUPONS.Address2, COUPONS.City, 
COUPONS.State, COUPONS.ZIP, COUPONS.PQBSSN, COUPONS.EmployerCode 
ordered by the COUPONS.DateDue. 

のように日付がの形式になります。日付範囲が01/01/2009 - 12/01/2009のレコードのみを選択し、そのうちの最も古いレコードを6つ選択します。

私は少しこれに猿を持ち、運がない。私はこれがかなり基本的だと知っていますが、私はちょうどこの仕事をすることはできません。ここで、テーブルから日付を取得するために使用するSQLの選択です。

SELECT COUPONS.DocType, COUPONS.PayTo, COUPONS.ContactName, COUPONS.ContactNumber, 
COUPONS.DocFooter, COUPONS.PQBName, COUPONS.LetterDate, COUPONS.RetireeFirstName, 
COUPONS.RetireeLastName, COUPONS.Address1, COUPONS.Address2, COUPONS.City, 
COUPONS.State, COUPONS.ZIP, COUPONS.PQBSSN, COUPONS.EmployerCode, COUPONS.AmountDue, 
COUPONS.DateDue, Right([DateDue],4)+Left([DateDue],2)+Mid([datedue],4,2) AS SORTDATE 
FROM COUPONS 
ORDER BY COUPONS.DocType, COUPONS.PayTo, COUPONS.ContactName, COUPONS.ContactNumber, 
COUPONS.DocFooter, COUPONS.PQBName, COUPONS.LetterDate, Right([DateDue],4)+Left 
([DateDue],2)+Mid([datedue],4,2); 
+0

すべての「日付」フィールドでその期間を使用していますか?または何ですか – whatsisname

+0

3つの単語:エイリアスを使用してください。 – VVS

+0

私はTOPに何かを忘れていますか?グループごとにTOP 6を返すにはどうすればいいですか?私は成功の前にTOPを使いましたが、各グループのTOP 6を1つのテーブルに戻す方法が不明です。 COUPONS.DocType、COUPONS.PayTo、COUPONS.ContactName、COUPONS.ContactNumber、COUPONS.DocFooter、COUPONS.PQBName –

答えて

1

私はあなたの問題を理解すると思う - 私はあなたの日付の問題を扱うに入らない解決策を与えてみましょう - いくつかあります上記の解決策の

PQBSSN DATE PQBNAME 
1 1/1/2009 A 
1 1/2/2009 A 
1 1/3/2009 A 
1 1/4/2009 Z 
1 1/5/2009 Z 
1 1/6/2009 Z 
2 1/1/2009 B 
2 1/2/2009 B 
2 1/3/2009 B 
2 1/4/2009 B 
2 1/5/2009 B 
2 1/6/2009 B 
3 1/1/2009 C 
3 1/2/2009 C 
3 1/3/2009 C 
3 1/4/2009 C 
3 1/5/2009 C 
3 1/6/2009 C 

SELECT C1.PQBSSN, C1.PQBNAME, C3.Date 
FROM [SELECT DISTINCT CA.PQBSSN, CA.PQBNAME FROM COUPONS AS CA]. AS C1, 
    [SELECT DISTINCT CB.DATE FROM COUPONS AS CB]. AS C3 
WHERE C3.DATE IN 
    (SELECT TOP 2 C2.DATE FROM COUPONS AS C2 WHERE C2.PQBSSN = C1.PQBSSN ORDER BY C2.DATE); 

内訳:

CA選択が非日付情報の一意の行に

を与えるCBが選択テーブル

ですべての日付を与え、このデータを考えると

"WHERE C3.DATE"を選択すると、一致する各グループに適用される日付が表示されます。グループ化行に一意のキーがない場合は、独立したフィールドごとにこの選択のWHEREをチェックする必要があります。

これは与える:

PQBSS PQBNAME Date 
    1 A 1/1/2009 
    1 Z 1/1/2009 
    2 B 1/1/2009 
    3 C 1/1/2009 
    1 A 1/2/2009 
    1 Z 1/2/2009 
    2 B 1/2/2009 
    3 C 1/2/2009 

私はこれがあなたのテーブルの簡易版である知っているが、私はそれがあなたの両端を実現だと思います。

+0

AmountDueを行に戻すために別のステップを追加する必要がありましたが、これを修正したバージョンでは私が探していた結果が得られました。私は事を2つの異なるクエリに分割してしまった。 1つは必要な日付を返し、もう1つはAmountDueを追加しました。 –

+0

ステップ1:(長いフィールドのリストを...に置換) SELECT C1.DocType、... C3.DateDue FROM [SELECT DISTINCT CA.DocType、CA.PayTo、CA.ContactName、CA.ContactNumber、 CA.Address1、CA.Address2、CA.City、CA.State、CA.ZIP、CA.PQBSSN、CA.EmployerCodeからCOUPONS1 ASを削除します。 CA]。 AS C1、[CBからCBへのディスカバリを選択します。 C3.DateDue INはC1.PQBSSN、C1.DocFooter、C1.LetterDate、C3に ORDERを(COUPONS1 AS C2 C2.PQBSSN = C1.PQBSSN ORDER BY C2.DateDueの上位6 C2.DateDue選択)C3 AS .DateDue; –

+0

ステップ2:AmountDueフィールドを回復するためにSTEP 1クエリを元のテーブルにリンクしました。 ありがとうございました。すべての答えとインサイトはとても役に立ちました。 –

0

おそらくあなたは、この

Right([DateDue],4)+Left([DateDue],2)+Mid([datedue],4,2); 

(例:= 2021 1996 + 04 + 21)のような日付値を追加している

ので

Right([DateDue],4),Left([DateDue],2),Mid([datedue],4,2); 
ご注文句でこれを試します

または値を追加するのではなく、値を連結してみてください:

Right([DateDue],4) & Left([DateDue],2) & Mid([datedue],4,2); 

(例:1996 + 04 + 21 = 19960421)

それは確かにちょうどトップ句を使用した後。私はそれが問題になるかもしれないことに気付かなかった、ごめんなさい。

0

私はアクセスの専門家ではないんだけど、私はAccessのバージョンがそれをサポートしている場合は、 "SELEC TOP" を使用することができると思う:右([DateDue]、4)BY

SELECT TOP 6 COUPONS.DocType, COUPONS.PayTo, COUPONS.ContactName, COUPONS.ContactNumber, COUPONS.DocFooter, COUPONS.PQBName, COUPONS.LetterDate, COUPONS.RetireeFirstName, COUPONS.RetireeLastName, COUPONS.Address1, COUPONS.Address2, COUPONS.City, COUPONS.State, COUPONS.ZIP, COUPONS.PQBSSN, COUPONS.EmployerCode, COUPONS.AmountDue, COUPONS.DateDue, Right([DateDue],4)+Left([DateDue],2)+Mid([datedue],4,2) AS SORTDATE FROM COUPONS 

ORDERを+ Left([DateDue]、2)+ Mid([日付]、4,2)、COUPONS.DocType、COUPONS.PayTo、COUPONS.ContactName、COUPONS.ContactNumber、COUPONS.DocFooter、COUPONS.PQBName、COUPONS.LetterDate

1

データベースを制御できるがテキストベースの日付を使用する必要がある場合は、ODBC標準形式を使用して日付を格納します。

yyyy-mm-dd    // if there's no time element 
yyyy-mm-dd HH:MM:ss  // if time is needed as well 

これは、いくつかの明確な利点があります。

  • 世界に優しい、米国ではなく、MM-DD-yyyyは当然日付でDD-MM-YYYY
  • ソートを意味と思うかもしれユーザーのためにので、普通の<と>演算子は正常に動作します(これらの演算はテキスト比較を行いますが、実際にはテキストを日付に変換することはありません)。
  • ビジネス層では、コードをまったく調整しなくても、この形式の日付を正しく読み取ることができます
  • 実際の日付のないフィールドがある場合、多くの場合と同じようにCONVERTすでに投稿されている提案の(たとえば、「Next Tuesday」や「N/A」のようなダーティ値を扱っていて、データベースから駆除できない場合など)。)

現在の日付データが一貫した形式であると仮定して、既存の日付データを変換するのは、RIGHT()、LEFT()などを使用したUPDATEの簡単な行為です。あなたのデータをより容易に照会することができる形式で格納されると

、それは簡単な問題だ:あなたのグループ化の問題については

SELECT TOP 6 * FROM mytable WHERE mydate BETWEEN startdate AND enddate ORDER BY mydate DESC 

、私は答えを提案するだけでなく、十分な質問を理解していません。しかし、最も効率的なテキスト形式で保存された日付データを取得することは、他のすべてを並べ替えるのに役立ちます。

[OK]を、私はあなたのグループ化の問題で刺しを取るつもりです:

SELECT DISTINCT DueDate, DocType, PayTo, ContactName, ContactNumber, [...other fields...] 
FROM coupons c1 
WHERE CDate(c1.DueDate) BETWEEN '01/01/2000' AND '01/01/2009' 
    /* Here's where the "grouping" happens--actually just filtering out the others */ 
    AND (SELECT COUNT(*) FROM coupons c2 WHERE 
    CDATE(c1.DueDate) >= CDATE(c2.DueDate) 
    AND c2.DocType=c1.DocType 
    AND c2.ContactName=c1.ContactName 
    AND c2.ContactNumber=c1.ContactNumber 
    [...test the other fields...] 
    ) <= 6 

私はこのサブクエリが動作するかどうかを知るために十分なジェットSQLのインとアウトを覚えていないことができますが、私は考えますそうなる。

0

あなたの質問は、(書式男!!)私はあなたの最初の質問をオフに行くつもりです読みにくいですので。日付が文字として表現されている場合は、6つの最古の日付を選択しない方法

SELECT top 6 CAST(datedue as datetime) as DateDue from test order by DateDue asc 
+0

オペレータは各グループから最も古い6行を取得します – spencer7593

+0

CAST()はJet SQL関数ではありません。 「sql」タグは、MS-ACCESSタグと組み合わせて使用​​する場合、MS SQLを意味するものではありません。これは、Accessで使用されるJet SQLについての質問であることを意味します。 –

0

私はあなたの問題の権利を読んでいる場合、あなたが日付のようなデータが含まれているテキストフィールドを持っていることが表示されます:

あなたがそれまでにオーダーを行い、日時としてdatedueをキャストする必要がありますそれを時系列で(ある範囲内で)並べ替えることができるようにしたいと考えています。いくつかの簡単なグーグルの後

、アクセスはあなたが日付に文字列データを変換するために使用することができますCDate関数()関数を持っていることが表示されます。

: - (アクセスするための構文は、おそらく似ていますが、多少異なる場合があり、少なくとも、SQL Serverの)第二に、その問題に対処あなたが持っていると、実際のクエリは、おそらくこのようになります日付範囲を選択します
SELECT TOP 6 [...] 
FROM [...] 
WHERE DateDue BETWEEN @BeginDate AND @EndDate 
ORDER BY DateDue ASC 

日付範囲内の6つの最も古いエントリを取得する方法の一般的な考え方です。それに取り組んで完了していない

+0

OPは、日付範囲内ではなく、各グループから最古の6レコードを求めます。 – spencer7593

+0

もう少し混乱しているOPを再読すると、それは私にとってはどちらのようにも聞こえます。どちらの場合でも... – CloudyMusic

+0

日付をテキストとして保存するのはちょっと面倒なことです。索引の有用性を失うだけでなく、すべてのデータ操作機能を失います。それは本当に悪いことです。 –

0

答え、...

問題を修正再表示するには、次のクエリは、あまりにも多くの行を返して、あなたが 7のための個別値の各「グループ」のための唯一の6行をしたいです 最初の6つの列は、ORDER BY句にリストされています。

あなたはすでに問題を解決しました。一般的な意見とは反対に、この問合せを機能させるためにDATETIMEにキャストする必要はありません。問題はDATETIME式でもVARCHAR式でも同じです。各グループの「最低」のn値が必要です。この結果は、単一のクエリに設定され得るために

、私はこれはアクセスが共通テーブルexpresssionsをサポートしていない、インライン・ビューとstopkey述語を必要とするように起こっていると思いますか?

などです。

WITH cte AS 
(SELECT ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...) AS ROWNUM 
     , ... 
    FROM COUPONS c 
) 
SELECT ... 
    FROM cte 
WHERE cte.ROWNUM <= 6 

- または -

SELECT TOP 6 ... 
    FROM ... 
GROUP 
    BY ... 

答え、 "人間が読める" ように再フォーマット、OPから


サンプルSQLステートメントを完了していない:

SELECT c.DocType 
    , c.PayTo 
    , c.ContactName 
    , c.ContactNumber 
    , c.DocFooter 
    , c.PQBName 
    , c.LetterDate 
    , c.RetireeFirstName 
    , c.RetireeLastName 
    , c.Address1 
    , c.Address2 
    , c.City 
    , c.State 
    , c.ZIP 
    , c.PQBSSN 
    , c.EmployerCode 
    , c.AmountDue 
    , c.DateDue 
    , Right(c.[DateDue],4)+Left(c.[DateDue],2)+Mid(c.[DateDue],4,2) AS SORTDATE 
    FROM COUPONS c 
ORDER 
    BY c.DocType 
    , c.PayTo 
    , c.ContactName 
    , c.ContactNumber 
    , c.DocFooter 
    , c.PQBName 
    , c.LetterDate 
    , Right(c.[DateDue],4)+Left(c.[DateDue],2)+Mid(c.[DateDue],4,2) 
+1

Spencer7593:これはまさに問題です。私は改造された日付をそこに入れていたので、簡単に並べ替えて、それを日付の方法で明確に並べることができました。 –

+0

Spencer7593:すべてのコメントが死んでいます。日付は問題ではなく、特にこのアプリケーションの最適化もありません。返されるデータの量は少なくなります。 DateDueには常にデータが入力され、データのインポート前に検証/境界チェックが行われます。それが役に立つなら、複数の選択肢を追加することができます。私がこれを解決できない場合は、データをテンポラリテーブルにコピーし、データを繰り返し処理し、自分のパラメータの外にあるエントリを削除するルーティンを書くことができます。私はちょうどそれがSELECTで直接行うことができる裁定を持っていた。あなたの患者の皆様、ありがとうございました! –

+0

@Scott:私の答えは否定的な票を集めています。もし私がもっと得れば、私は「良い市民」になり、私の答えを取り除くでしょう。たぶん、私は群衆に参加し、あなたが質問していない質問に答えを投稿します。「フォーマットされた文字列を日時に変換するにはどうすればよいですか? – spencer7593

1

すべての行に日付文字列があることが確かであれば、最も簡単なVBは日付値に変換することができます:CDate([DateDue])。しかし、NULLで失敗します。

それではあなたが最も古い行を取得することができます

Select Top 6 * 
From myTable 
ORDER BY CDate([DateDue]) ASC 
+0

+1は、すべてのデータが、この関数が動作するための日付に変換できる値を持たなければならないという点を示しています。 – richardtallent

+0

OPでは、最も古い6つのレコードだけでなく、各グループから最古の6行が必要です。 – spencer7593