2009-06-10 4 views
2

Access 2003에서이 값을 사용하고 있습니다. 이것이 잘못된 위치에 있으면 용서해 주겠지 만 누군가 도와 줄 수 있기를 바랍니다.SQL을 선택하십시오.

날짜 필드를 나타내는 텍스트가있는 여러 레코드가있는 테이블이 있습니다. 날짜 형식처럼에 있습니다

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. 

처럼 : "2009-06-01"나는 각 그룹의 범위에 속하는 모든 테이블의 필드 만 6 개 오래된 행을 선택해야합니다 : 날짜 범위가 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

세 단어 : 별칭을 사용하십시오. – VVS

+0

TOP에 뭔가 빠져 있습니다. 각 그룹에 대해 TOP 6을 반환하도록하려면 어떻게합니까? 성공하기 전에 TOP를 사용했지만 각 그룹의 TOP 6을 한 테이블에 반환하는 방법을 잘 모르겠습니다. 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가 선택이

가 인증 기관을 선택

이 테이블의 모든 날짜를 을 제공 날짜가 아닌 정보의 고유 행을 제공

"WHERE C3.DATE"선택은 일치하는 각 그룹에 적용되는 날짜를 제공합니다. 그룹화 행에 대한 고유 키가 없으면 모든 독립 필드에 대해이 선택의 위치에 점검을 넣어야합니다.

이 부여 :

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를 다시 행으로 가져 오려면 다른 단계를 추가해야했지만이 수정 된 버전에서는 찾고 있던 결과가 생성되었습니다. 나는 두 가지 다른 질의로 그 일을 분할했다. 하나는 필요한 날짜를 반환했고, 다른 하나는 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 FRUP COUPONS1 AS에서 CA.PQBName, CA.PQBName, CA.PQBName, CA.LetterDate, CA.RetireeFirstName CA]. C1과 마찬가지로, [CB에서 COUPONS1로부터 DISTINCT CB.DateDue를 선택하십시오]. AS C3 WHERE C3.DateDue IN (SELECT TOP 6 C2.DateDue FROM COUPONS1 AS C2 WHERE C2.PQBSSN = C1.PQBSSN ORDER BY C2.DateDue) ORDER BY C1.PQBSSN, C1.DocFooter, C1.LetterDate, C3 .DateDue; –

+0

2 단계 : AmountDue 필드를 복구하기 위해 STEP 1 쿼리를 원본 테이블에 연결했습니다. 도움을 주신 모든 분들께 감사드립니다. 모든 대답과 insites는 매우 도움이되었다. –

0

당신은 같은 날짜 값을 추가하는이

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

(예 : 1996 + 04 = 2021 + 21)

그래서 주문 절에서 이것을 시도

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

값을 추가하는 대신 concatening 해보십시오.

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

(예 : 1996 + 04 + 21 = 19960421)

즉 실제로 바로 위에 절을 사용 후. 그게 문제가 될 수 있다는 것을 깨닫지 못했습니다. 미안 해요.

0

내가 액세스의 전문가가 아니지만, 내가 Access 버전이 지원하는 경우 당신이 "SELEC TOP"를 사용할 수 있다고 생각 : 오른쪽 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를 ([DateDue, 4) + 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 
01 23,516,

이 몇 가지 뚜렷한 장점이 있습니다

  • 세계 친화적, 미국에없는 및 MM-DD-YYYY 자연스럽게 날짜 DD-MM-YYYY에게
  • 정렬을 의미 생각할 수 있습니다 사용자를 , 그래서 정상적인 < 및> 연산자는 잘 작동합니다 (그리고 이러한 연산은 텍스트 비교를 수행하고 실제로 텍스트를 날짜로 변환하지 않습니다).
  • 귀하의 비즈니스 계층은 코드를 전혀 수정하지 않고도이 형식의 날짜를 올바르게 읽을 수 있습니다.
  • 실제 날짜가없는 입력란은 많은 수의 CONVERT() 오류를 생성하지 않습니다. 이미 게시 된 제안 사항 중 (예를 들어, "다음 화요일"또는 "해당 없음"과 같이 더티 값을 처리하는 경우 데이터베이스에서 제거 할 수 없습니다.)

현재 날짜 데이터가 일관된 형식이라고 가정하고 RIGHT(), LEFT() 등을 사용하여 기존 날짜 데이터를 쉽게 변환 할 수 있습니다.

당신의 그룹화 문제에 관해서는
SELECT TOP 6 * FROM mytable WHERE mydate BETWEEN startdate AND enddate ORDER BY mydate DESC 

, 내가 대답을 제안 충분히 질문을 이해하지 않습니다 데이터가 더 쉽게 조회 할 수있는 형식으로 저장되면

, 그것은 간단한 문제입니다 . 그러나 가장 효율적인 텍스트 형식으로 저장된 날짜 데이터를 가져 오는 것은 다른 모든 것을 정렬하는 데 도움이됩니다.

좋아, 나는 당신의 그룹화 문제에 자상을거야 :

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

OP는 각 그룹에서 가장 오래된 6 개의 행을 원합니다. – spencer7593

+0

CAST()는 Jet SQL 함수가 아닙니다. "sql"태그는 MS-ACCESS 태그와 함께 사용될 때 MS SQL을 의미하지 않습니다. 단지 Access에서 사용되는 Jet SQL에 관한 것입니다. –

0

나는 당신의 문제를 잘 읽고 있어요 경우, 당신이 날짜 같은 데이터를 포함하는 텍스트 필드가 나타납니다 :

당신은 그때까지 주문을 수행합니다 날짜로 datedue 캐스팅 할 필요가 , 당신은 그것을 시간순으로 (범위 내에서) 정렬 할 수 있기를 원합니다.

몇 가지 빠른 인터넷 검색 후 Access에 문자열 데이터를 날짜로 변환하는 데 사용할 수있는 CDate() 함수가있는 것으로 보입니다. 둘째로, 문제가 해결되면 날짜 범위를 선택하는 실제 쿼리는 다음과 비슷할 것입니다 (적어도 Sql Server에서는 Access 구문이 비슷하지만 약간 다를 수 있음).

SELECT TOP 6 [...] 
FROM [...] 
WHERE DateDue BETWEEN @BeginDate AND @EndDate 
ORDER BY DateDue ASC 

날짜 범위 내에서 가장 오래된 항목 6 개를 얻는 방법에 대한 일반적인 개념입니다.

+0

OP는 날짜 범위가 아니라 각 그룹에서 가장 오래된 6 개의 레코드를 원합니다. – spencer7593

+0

다소 혼란스러운 OP를 다시 읽으면서 저에게 두 가지처럼 들립니다. 두 경우 모두 ... – CloudyMusic

+0

날짜를 텍스트로 저장하는 것은 무서운 생각입니다.인덱스의 유용성을 잃을뿐만 아니라 모든 데이터 조작 기능을 잃게됩니다. 정말 나쁜 일입니다. –

0

대답 완료되지,

문제 재 작성 ... 그것은 작업 : 쿼리가 너무 많은 행을 반환, 당신이 원하는을 일곱에 대한 고유 값의 각각의 '그룹'에 대한 여섯 명 밖에 행 처음 6 개의 열은 ORDER BY 절에 나열됩니다.

이미 날짜 문제가 해결되었습니다. 보편적 인 의견과 달리이 쿼리를 작동 시키려면 DATETIME으로 변환 할 필요가 없습니다. 문제는 DATETIME 표현식이나 VARCHAR 표현식에 관계없이 똑같습니다. 각 그룹에 대해 "가장 낮은"n 값만 원할뿐입니다.

단일 쿼리에서이 결과 집합을 얻으려면 인라인보기가있는 정지 키 조건자가 필요하다고 생각합니다. Access는 공통 테이블 표현을 지원합니까?

예를 들면.

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 ... 

대답은 "사람이 읽을 수"로 포맷, 영업 이익에서


샘플 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 : 내 대답은 부정적인 표를 얻고 있습니다. 더 많은 것을 얻는다면, 나는 "좋은 시민"이되어 나의 대답을 제거 할 것이다. 어쩌면 내가 군중에 가입하고 질문하지 않은 질문에 대한 답변을 게시 할 것입니다. "형식화 된 문자열을 datetime으로 변환하려면 어떻게합니까?" – spencer7593

1

모든 행에 날짜 문자열이 있다고 확신하는 경우, 가장 쉬운 VB에서 datevalue로 변환하는 것이 CDate ([DateDue])입니다. 하지만 NULL에서는 실패합니다.

그럼 당신은 오래된 행 얻을 수 있습니다 : - 내가 당신에게 당신의 날짜 문제를 다루는로하지 않는 솔루션을 제공 할 수 -

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

+1 모든 데이터가이 기능이 작동하는 날짜로 변환 될 수있는 값을 가져야한다는 점을 확인하기 위해 +1. – richardtallent

+0

OP에는 가장 오래된 6 개의 레코드가 아니라 각 그룹의 가장 오래된 6 개의 행이 필요합니다. – spencer7593

관련 문제