database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
PostgreSQL
Firebird
Oracle
Informix
Sybase
ㆍMS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
MS-SQL Q&A 6595 게시물 읽기
No. 6595
근사치 필드 까지만 select 할수 있는 쿼리좀...부탁합니다
작성자
김우성(babokws)
작성일
2012-12-26 20:40
조회수
10,945

가격이라는 필드 100개중 실제로는 21개 각각(2,000 3,420 10,000)이러한 금액들이 있습니다.
첫번째부터 21개를 합산해보니 99,840원이라는 값이 나오고 22개를 합산하면 112,100원이 나오네요
그렇다면 21개99,840원이 100,000원에 가깝네요
구하고자하는 select 는 100,000원에 가장근사치가 될수있는 합이 1번부터 몇개까지를 더하면 되는지...
만약21개라면 21개의 필드가 출력됐으면 좋겠습니다...
쿼리문이 있을 까요... 아시는분들 좀 갈켜주세요...^^

어떤분이 이런 답변을 보내주셨는데 뭔지 잘 모르겠어요...

declare @amt int

set @amt = 100000 ;

with test
as (
select 1 no ,6347 amt union all
select 2 no ,7047 amt union all
select 3 no ,7843 amt union all
select 4 no ,4156 amt union all
select 5 no ,4040 amt union all
select 6 no ,971 amt union all
select 7 no ,1707 amt union all
select 8 no ,374 amt union all
select 9 no ,6779 amt union all
select 10 no ,7361 amt union all
select 11 no ,952 amt union all
select 12 no ,3527 amt union all
select 13 no ,1361 amt union all
select 14 no ,3693 amt union all
select 15 no ,2857 amt union all
select 16 no ,1996 amt union all
select 17 no ,8418 amt union all
select 18 no ,7291 amt union all
select 19 no ,3479 amt union all
select 20 no ,6918 amt union all
select 21 no ,1655 amt union all
select 22 no ,9835 amt union all
select 23 no ,1453 amt union all
select 24 no ,1877 amt union all
select 25 no ,8930 amt union all
select 26 no ,8416 amt union all
select 27 no ,982 amt union all
select 28 no ,2400 amt union all
select 29 no ,786 amt union all
select 30 no ,937 amt union all
select 31 no ,5494 amt union all
select 32 no ,1283 amt union all
select 33 no ,2528 amt union all
select 34 no ,768 amt union all
select 35 no ,902 amt union all
select 36 no ,7418 amt union all
select 37 no ,368 amt union all
select 38 no ,7712 amt union all
select 39 no ,7168 amt union all
select 40 no ,797 amt union all
select 41 no ,2304 amt union all
select 42 no ,2968 amt union all
select 43 no ,2023 amt union all
select 44 no ,1118 amt union all
select 45 no ,3894 amt union all
select 46 no ,2476 amt union all
select 47 no ,501 amt union all
select 48 no ,4633 amt union all
select 49 no ,5956 amt union all
select 50 no ,7321 amt union all
select 51 no ,6152 amt union all
select 52 no ,5206 amt union all
select 53 no ,7898 amt union all
select 54 no ,8820 amt union all
select 55 no ,4052 amt union all
select 56 no ,1269 amt union all
select 57 no ,1224 amt union all
select 58 no ,4963 amt union all
select 59 no ,454 amt union all
select 60 no ,2816 amt union all
select 61 no ,1017 amt union all
select 62 no ,309 amt union all
select 63 no ,3829 amt union all
select 64 no ,8649 amt union all
select 65 no ,825 amt union all
select 66 no ,6911 amt union all
select 67 no ,1932 amt union all
select 68 no ,2454 amt union all
select 69 no ,3227 amt union all
select 70 no ,9941 amt union all
select 71 no ,2139 amt union all
select 72 no ,526 amt union all
select 73 no ,136 amt union all
select 74 no ,8667 amt union all
select 75 no ,5222 amt union all
select 76 no ,4016 amt union all
select 77 no ,8423 amt union all
select 78 no ,3018 amt union all
select 79 no ,4238 amt union all
select 80 no ,4708 amt union all
select 81 no ,9240 amt union all
select 82 no ,8715 amt union all
select 83 no ,881 amt union all
select 84 no ,4286 amt union all
select 85 no ,1666 amt union all
select 86 no ,2225 amt union all
select 87 no ,5491 amt union all
select 88 no ,8360 amt union all
select 89 no ,7187 amt union all
select 90 no ,5515 amt union all
select 91 no ,9801 amt union all
select 92 no ,1857 amt union all
select 93 no ,7876 amt union all
select 94 no ,8420 amt union all
select 95 no ,6287 amt union all
select 96 no ,4061 amt union all
select 97 no ,1899 amt union all
select 98 no ,8373 amt union all
select 99 no ,6045 amt union all
select 100 no ,5209 amt ) ,
 result as (
select a.no , abs(sum(b.amt) - @amt) absamt
  from test a, test b
 where a.no >= b.no
group by a.no )
select *
  from test
 where no <= (   select no
      from result
     where absamt = ( select min(absamt)
           from result ) )

이 글에 대한 댓글이 총 27건 있습니다.

 답변을 받으셨던 것을 CTE를 사용하지 않는 버전으로 고쳐봤습니다.

 

declare @amt int

set @amt = 100000 ;

 

create table test(

no int

, amt int

)

;

 

insert into test( no, amt )

select 1 no ,6347 amt union all

select 2 no ,7047 amt union all

select 3 no ,7843 amt union all

select 4 no ,4156 amt union all

select 5 no ,4040 amt union all

select 6 no ,971 amt union all

select 7 no ,1707 amt union all

select 8 no ,374 amt union all

select 9 no ,6779 amt union all

select 10 no ,7361 amt union all

select 11 no ,952 amt union all

select 12 no ,3527 amt union all

select 13 no ,1361 amt union all

select 14 no ,3693 amt union all

select 15 no ,2857 amt union all

select 16 no ,1996 amt union all

select 17 no ,8418 amt union all

select 18 no ,7291 amt union all

select 19 no ,3479 amt union all

select 20 no ,6918 amt union all

select 21 no ,1655 amt union all

select 22 no ,9835 amt union all

select 23 no ,1453 amt union all

select 24 no ,1877 amt union all

select 25 no ,8930 amt union all

select 26 no ,8416 amt union all

select 27 no ,982 amt union all

select 28 no ,2400 amt union all

select 29 no ,786 amt union all

select 30 no ,937 amt union all

select 31 no ,5494 amt union all

select 32 no ,1283 amt union all

select 33 no ,2528 amt union all

select 34 no ,768 amt union all

select 35 no ,902 amt union all

select 36 no ,7418 amt union all

select 37 no ,368 amt union all

select 38 no ,7712 amt union all

select 39 no ,7168 amt union all

select 40 no ,797 amt union all

select 41 no ,2304 amt union all

select 42 no ,2968 amt union all

select 43 no ,2023 amt union all

select 44 no ,1118 amt union all

select 45 no ,3894 amt union all

select 46 no ,2476 amt union all

select 47 no ,501 amt union all

select 48 no ,4633 amt union all

select 49 no ,5956 amt union all

select 50 no ,7321 amt union all

select 51 no ,6152 amt union all

select 52 no ,5206 amt union all

select 53 no ,7898 amt union all

select 54 no ,8820 amt union all

select 55 no ,4052 amt union all

select 56 no ,1269 amt union all

select 57 no ,1224 amt union all

select 58 no ,4963 amt union all

select 59 no ,454 amt union all

select 60 no ,2816 amt union all

select 61 no ,1017 amt union all

select 62 no ,309 amt union all

select 63 no ,3829 amt union all

select 64 no ,8649 amt union all

select 65 no ,825 amt union all

select 66 no ,6911 amt union all

select 67 no ,1932 amt union all

select 68 no ,2454 amt union all

select 69 no ,3227 amt union all

select 70 no ,9941 amt union all

select 71 no ,2139 amt union all

select 72 no ,526 amt union all

select 73 no ,136 amt union all

select 74 no ,8667 amt union all

select 75 no ,5222 amt union all

select 76 no ,4016 amt union all

select 77 no ,8423 amt union all

select 78 no ,3018 amt union all

select 79 no ,4238 amt union all

select 80 no ,4708 amt union all

select 81 no ,9240 amt union all

select 82 no ,8715 amt union all

select 83 no ,881 amt union all

select 84 no ,4286 amt union all

select 85 no ,1666 amt union all

select 86 no ,2225 amt union all

select 87 no ,5491 amt union all

select 88 no ,8360 amt union all

select 89 no ,7187 amt union all

select 90 no ,5515 amt union all

select 91 no ,9801 amt union all

select 92 no ,1857 amt union all

select 93 no ,7876 amt union all

select 94 no ,8420 amt union all

select 95 no ,6287 amt union all

select 96 no ,4061 amt union all

select 97 no ,1899 amt union all

select 98 no ,8373 amt union all

select 99 no ,6045 amt union all

select 100 no ,5209 amt 

;

 

 

select test.*

from test

inner join (

select top (1) a.no 

from test a, test b

where a.no >= b.no

group by a.no 

order by abs(sum(b.amt) - @amt) 

) as result

on test.no <= result.no

;

 

drop table test

;

우욱님이 2012-12-27 07:14에 작성한 댓글입니다. Edit

select test.* from test inner join (select top (1) a.no from test a, test b where a.no >= b.no group by a.no 

order by abs(sum(b.amt) - @amt)  ) as result on test.no <= result.no

실행시

Server: Msg 170, Level 15, State 1, Line 7
Line 7: Incorrect syntax near '('.
 

에러메세지 나서  top (1) -> top 1 이렇게 고쳤는데

Server: Msg 137, Level 15, State 2, Line 15
Must declare the variable '@amt'.
 

이런 에러가 납니다. 좀더 구체적으로 쉽게 설명좀 부탁드립니다...수고하세요

김우성님이 2012-12-30 01:16에 작성한 댓글입니다. Edit

 TOP (1)로는 에러가 나고 TOP 1로는 가능하다면 아마 SQL 2000 이겠죠?

사용하시는 SQL 버전쯤이야 무난히 극복하실 수 있기에 질문에 적지 않으셨던 부분이지 않았겠나.. 싶구요...

 

 

declare @amt 로 시작하는 문장부터 맨 끝까지 한번에 실행하셔야 에러가 안나실 겁니다.

 

 

select top (1) a.no 

from test a, test b

where a.no >= b.no

group by a.no 

order by abs(sum(b.amt) - @amt) 

에서 self-join을 하는데 a를 기준으로 자기를 포함해서 자기보다 작은 모든 entity들에 대해 join을 수행하여 sum(b.amt)에서 원하는 값(@amt)을 빼서 abs()함수로 절대값을 구하여 이를 오름 정렬로 정렬하고 그 중에 가장 근사치를 갖게하는 no를 구한 후에

 

 

select test.*

from test

inner join (

중간생략

) as result

on test.no <= result.no

;

그렇게 구해진 no보다 작은 모든 entity를 출력해 냅니다.

우욱님이 2013-01-01 20:45에 작성한 댓글입니다. Edit

declare @amt int
set @amt = 100000 ;

create table test(
 no int
 , amt int
)
;

insert into test( no, amt )
select 1 no ,6347 amt union all
select 2 no ,7047 amt union all
select 3 no ,7843 amt union all
select 4 no ,4156 amt union all
select 5 no ,4040 amt union all
select 6 no ,971 amt union all
select 7 no ,1707 amt union all
select 8 no ,374 amt union all
select 9 no ,6779 amt union all
select 10 no ,7361 amt union all
select 11 no ,952 amt union all
select 12 no ,3527 amt union all
select 13 no ,1361 amt union all
select 14 no ,3693 amt union all
select 15 no ,2857 amt union all
select 16 no ,1996 amt union all
select 17 no ,8418 amt union all
select 18 no ,7291 amt union all
select 19 no ,3479 amt union all
select 20 no ,6918 amt union all
select 21 no ,1655 amt union all
select 22 no ,9835 amt union all
select 23 no ,1453 amt union all
select 24 no ,1877 amt union all
select 25 no ,8930 amt union all
select 26 no ,8416 amt union all
select 27 no ,982 amt union all
select 28 no ,2400 amt union all
select 29 no ,786 amt union all
select 30 no ,937 amt union all
select 31 no ,5494 amt union all
select 32 no ,1283 amt union all
select 33 no ,2528 amt union all
select 34 no ,768 amt union all
select 35 no ,902 amt union all
select 36 no ,7418 amt union all
select 37 no ,368 amt union all
select 38 no ,7712 amt union all
select 39 no ,7168 amt union all
select 40 no ,797 amt union all
select 41 no ,2304 amt union all
select 42 no ,2968 amt union all
select 43 no ,2023 amt union all
select 44 no ,1118 amt union all
select 45 no ,3894 amt union all
select 46 no ,2476 amt union all
select 47 no ,501 amt union all
select 48 no ,4633 amt union all
select 49 no ,5956 amt union all
select 50 no ,7321 amt union all
select 51 no ,6152 amt union all
select 52 no ,5206 amt union all
select 53 no ,7898 amt union all
select 54 no ,8820 amt union all
select 55 no ,4052 amt union all
select 56 no ,1269 amt union all
select 57 no ,1224 amt union all
select 58 no ,4963 amt union all
select 59 no ,454 amt union all
select 60 no ,2816 amt union all
select 61 no ,1017 amt union all
select 62 no ,309 amt union all
select 63 no ,3829 amt union all
select 64 no ,8649 amt union all
select 65 no ,825 amt union all
select 66 no ,6911 amt union all
select 67 no ,1932 amt union all
select 68 no ,2454 amt union all
select 69 no ,3227 amt union all
select 70 no ,9941 amt union all
select 71 no ,2139 amt union all
select 72 no ,526 amt union all
select 73 no ,136 amt union all
select 74 no ,8667 amt union all
select 75 no ,5222 amt union all
select 76 no ,4016 amt union all
select 77 no ,8423 amt union all
select 78 no ,3018 amt union all
select 79 no ,4238 amt union all
select 80 no ,4708 amt union all
select 81 no ,9240 amt union all
select 82 no ,8715 amt union all
select 83 no ,881 amt union all
select 84 no ,4286 amt union all
select 85 no ,1666 amt union all
select 86 no ,2225 amt union all
select 87 no ,5491 amt union all
select 88 no ,8360 amt union all
select 89 no ,7187 amt union all
select 90 no ,5515 amt union all
select 91 no ,9801 amt union all
select 92 no ,1857 amt union all
select 93 no ,7876 amt union all
select 94 no ,8420 amt union all
select 95 no ,6287 amt union all
select 96 no ,4061 amt union all
select 97 no ,1899 amt union all
select 98 no ,8373 amt union all
select 99 no ,6045 amt union all
select 100 no ,5209 amt
;

select test.*
from test
inner join (
 select top (1) a.no
 from test a, test b
 where a.no >= b.no
 group by a.no
 order by abs(sum(b.amt) - @amt)
) as result
on test.no <= result.no

여기까지 한번에 실행해보았는데요

Server: Msg 170, Level 15, State 1, Line 116
Line 116: Incorrect syntax near '('.
이런에러가 계속납니다.  어떻해야 되는거죠.  도와주세요...!^^

참고로 테이블은 outd_1212 이며

필드명은 tmamoney1입니다...

김우성(babokws)님이 2013-01-02 19:08에 작성한 댓글입니다.

 제가 첫번째로 드렸던 답변 중에서

create table ~~~

insert into ~~~

부분이야 test할 data를 생성하느라 필요했던 부분이라서 실제로 적용해서 사용하시기 위해서는 크게 의미가 없는 부분이고요

 

declare @amt int;

set @amt = 100000 ;

 

이 부분은 @amt 값을 설정하여 원하는 값을 유동적으로 설정하여 다음의 select 문을 값에 따라 매번 다르게 작성하지 않도록 하는 부분입니다.

 

키가 되는 select 문은 아래의 select문인데,

 

select test.*
from test
inner join (

select top 1 a.no 

-- 2000 이라 생각되어 ()를 뺐음을 눈여겨 보세요

from test a INNER JOIN test b ON a.no >= b.no

group by a.no 

order by abs(sum(b.amt) - @amt) 

) as result

on test.no <= result.no

;

 

위의 문장을 다음과 같이 단계 별로 실행을 해보세요. 물론 아래의 문장들은 test 테이블을 생성한 상태에서 돌려보셔야 합니다.

 

 

 

select *

from test a INNER JOIN test b ON a.no >= b.no

ORDER BY a.no, b.no

 

그럼 a테이블의 각 행에 대해 b테이블의 어떤 행들이 join되었는지 보이실꺼구요 물론 여기서 a테이블과 b테이블은 이름만 구분했지 실제로는 같은 테이블이 됩니다.

 

 

 

select a.no , sum(b.amt), sum(b.amt) - 100000 , abs(sum(b.amt) - 100000 ) 

from test a INNER JOIN test b ON a.no >= b.no

group by a.no 

ORDER BY a.no

 

이제는 group by를 통해 a테이블의 각 행에 대해 b테이블의 amt를 더한 결과, 더한 결과에서 100000을 뺀 결과, 그리고 그 결과에 절대값을 취한 결과를 눈으로 보실 수 있습니다. 여기에서는 쉽게 돌려보기 위해서 @amt를 사용하지 않고 상수값 100000을 사용했습니다.

 

 

 

select a.no , sum(b.amt), sum(b.amt) - 100000 , abs(sum(b.amt) - 100000 ) 

from test a INNER JOIN test b ON a.no >= b.no

group by a.no 

order by abs(sum(b.amt) - @amt) 

 

그럼 위의 문장을 돌려보시면 좀 이해가 되시죠?

 

 

 

select top 1 a.no 

from test a INNER JOIN test b ON a.no >= b.no

group by a.no 

order by abs(sum(b.amt) - @amt) 

 

그 중에서 가장 근사치 1개를 구해내도록 top 1 절을 수행합니다. 그럼 이제 원하는 no값을 구해냈으니 첫번째 부터 no까지 죽~ 출력만 하면 되겠죠.

 

 

select test.*

from test

where no <= (

select top 1 a.no 

from test a INNER JOIN test b ON a.no >= b.no

group by a.no 

order by abs(sum(b.amt) - @amt) 

)

order by no

 

조금 더 이해하기 쉽지 않을까 싶어서 where 절로 바꾸어봤습니다. 물론 결과는 같습니다.

 

 

이러면 좀 도움이 되실까요? ㅋ

우욱님이 2013-01-02 21:31에 작성한 댓글입니다. Edit

select test.*
from test
inner join (

 select top 1 a.no

-- 2000 이라 생각되어 ()를 뺐음을 눈여겨 보세요

 from test a INNER JOIN test b ON a.no >= b.no

 group by a.no

 order by abs(sum(b.amt) - @amt)

) as result

on test.no <= result.no

서버: 메시지 137, 수준 15, 상태 2, 줄 13
'@amt' 변수를 선언해야 합니다.

 


select a.no , sum(b.amt), sum(b.amt) - 100000 , abs(sum(b.amt) - 100000 )

 from test a INNER JOIN test b ON a.no >= b.no

 group by a.no

 order by abs(sum(b.amt) - @amt)

서버: 메시지 137, 수준 15, 상태 2, 줄 7
'@amt' 변수를 선언해야 합니다.

 

 

select top 1 a.no

 from test a INNER JOIN test b ON a.no >= b.no

 group by a.no

 order by abs(sum(b.amt) - @amt)

서버: 메시지 137, 수준 15, 상태 2, 줄 7
'@amt' 변수를 선언해야 합니다.

 

 

 

select test.*

from test

where no <= (

 select top 1 a.no

 from test a INNER JOIN test b ON a.no >= b.no

 group by a.no

 order by abs(sum(b.amt) - @amt)

)

order by no

서버: 메시지 137, 수준 15, 상태 2, 줄 13
'@amt' 변수를 선언해야 합니다.
 

문장마다 @amt 변수를 선언해야 합니다 라고나옵니다...왜 저는 않되는거죠

제발 답좀갈켜주세요...

우성대왕짱님이 2013-01-04 22:25에 작성한 댓글입니다. Edit

 아... 나름 설명을 한다고 중간 단계를 만들면서 @amt를 넣었었군요..

 

제가 드렸던 예제들 중에서 @amt를 모두 100000으로 바꿔서 실행을 해보세요.

 

(괜히 엄한 Ctrl+C와 Ctrl+V를 탓하며..... T,.T)

우욱님이 2013-01-06 05:59에 작성한 댓글입니다. Edit

거의 답이 나왔습니다...정말 감사드립니다.. 그리고 궁금한게 하나더 있어서요

test 란 테이블에 no 와  amt  두개의 필드가 있는데 no 는 없고 amt 필드만 있다고해도

같은 값을 구해낼수있을까요 없다면 기준점이되는 no 필드를 만들어야 되나요?

우성대왕짱님이 2013-01-06 12:43에 작성한 댓글입니다. Edit

  느낌상 2000을 사용하고 계신 것으로 생각이 드는데,

그렇다면 row_number() 함수를 사용할 수 없으므로

아무래도 no 컬럼이 있으셔야 할 것으로 보입니다.

우욱님이 2013-01-06 23:37에 작성한 댓글입니다. Edit

2000 -> 2005 로 갈아타면

2005의 쿼리문좀 부탁드립니다...

그리고 2000에서 amt 필드가 이미 20,000 개가 있는데

20,000개의 라인없이 한번에 no 필드를  어떻게 만들수 있나요?

우성대왕짱님이 2013-01-07 10:57에 작성한 댓글입니다.
이 댓글은 2013-01-07 11:00에 마지막으로 수정되었습니다. Edit

SELECT ROW_NUMBER() OVER( ORDER BY ( SELECT NULL ) ) AS no , amt FROM 해당테이블

;

와 같이 만들 수 있긴 합니다. 하지만 PK를 테이블에 꼭 생성하는 것이 MS 엔지니어의 권고사항인 만큼 정말 피치못할 이유가 없다면 별도의 컬럼(예를 들자면 no 같은)을 생성해서 해당 컬럼에 PK를 설정하는 것을 추천드립니다.

우욱님이 2013-01-07 13:08에 작성한 댓글입니다. Edit

SQL 2000에서 테이블명은 outm_1210 이고 실제컬럼들입니다.

A B C D B의합산값
2012-10-01 2500 0 07:13 2,500
2012-10-01 1450 0 07:37 3,950
2012-10-01 2200 0 07:50 6,150
2012-10-01 3500 0 07:57 9,650
2012-10-01 3800 0 08:06 13,450
2012-10-01 2500 0 09:02 15,950
2012-10-01 1400 0 09:14 17,350
2012-10-01 1000 0 09:28 18,350
2012-10-01 2200 0 09:42 20,550
2012-10-01 3400 0 09:51 23,950

다른 컬럼이 있기는 하지만 select 문에서는 필요가 없는듯하구요...
저는 select 해서 첫번째 라인부터 합산을해서 10,000에 가장 근사치인값들의 라인을 보고 싶은것입니다.

A B C D B의합산값
2012-10-01 2500 0 07:13 2,500
2012-10-01 1450 0 07:37 3,950
2012-10-01 2200 0 07:50 6,150
2012-10-01 3500 0 07:57 9,650

4버째라인 9,650원이 10,000에 가장 근사치네요, 두번째 표와 똑같이 select 하고 싶어요.

김우성(babokws)님이 2013-01-07 17:57에 작성한 댓글입니다.
이 댓글은 2013-01-07 18:14에 마지막으로 수정되었습니다.

 2000이고 테이블 구조가 그정도.... 라면

커서 뺑뺑이도 되겠죠 뭐

 

/* 샘플 테이블 및 데이터 

CREATE TABLE outm_1210(
  aa datetime         
  , bb int            
  , cc int
  , dd char(5)
);           
 
insert into outm_1210( aa, bb, cc, dd )
SELECT '2012-10-01', 2500, 0, '07:13' UNION ALL
SELECT '2012-10-01', 1450, 0, '07:37' UNION ALL
SELECT '2012-10-01', 2200, 0, '07:50' UNION ALL
SELECT '2012-10-01', 3500, 0, '07:57' UNION ALL
SELECT '2012-10-01', 3800, 0, '08:06' UNION ALL
SELECT '2012-10-01', 2500, 0, '09:02' UNION ALL
SELECT '2012-10-01', 1400, 0, '09:14' UNION ALL
SELECT '2012-10-01', 1000, 0, '09:28' UNION ALL
SELECT '2012-10-01', 2200, 0, '09:42' UNION ALL
SELECT '2012-10-01', 3400, 0, '09:51'
;
*/
 
 
DECLARE @aa DATETIME;
DECLARE @bb INT;
DECLARE @cc INT;
DECLARE @dd CHAR(5);
 
CREATE TABLE #tmp(  
  aa datetime         
  , bb int            
  , cc int
  , dd char(5)
  , cs INT
)
;
DECLARE @sum INT
;
SET @sum = 0
;
 
 
DECLARE cur CURSOR LOCAL FORWARD_ONLY FAST_FORWARD READ_ONLY
FOR
SELECT aa, bb, cc, dd FROM outm_1210
;
OPEN cur
;
FETCH NEXT FROM cur INTO @aa, @bb, @cc, @dd;
 
WHILE @@FETCH_STATUS = 0
BEGIN
IF ABS( 10000 - @sum - @bb ) < ABS( 10000 - @sum )
BEGIN
SET @sum = @sum + @bb
;
INSERT INTO #tmp( aa, bb, cc, dd, cs ) VALUES( @aa, @bb, @cc, @dd, @sum )
;
END
ELSE
BEGIN
BREAK
;
END
FETCH NEXT FROM cur INTO @aa, @bb, @cc, @dd;
END
 
CLOSE cur
;
DEALLOCATE cur
;
 
SELECT aa, bb, cc, dd, cs FROM #tmp
;
 
DROP TABLE #tmp
;
 

우욱님이 2013-01-08 07:35에 작성한 댓글입니다. Edit

커서 옵션 FORWARD_ONLY 및 FAST_FORWARD이(가) 충돌됩니다.라는 메세지때문에

DECLARE cur CURSOR LOCAL FORWARD_ONLY  READ_ONLY FOR
SELECT aa, bb, cc, dd FROM outm_1210

DECLARE cur CURSOR LOCAL  FAST_FORWARD READ_ONLY FOR
SELECT aa, bb, cc, dd FROM outm_1210
나누어서 실행시켰습니다...맞는건지 모르겠네요

OPEN cur
이름이 'cur'인 커서가 없습니다.

FETCH NEXT FROM cur INTO @aa, @bb, @cc, @dd WHILE @@FETCH_STATUS = 0
BEGIN
 IF ABS( 10000 - @sum - @bb ) < ABS( 10000 - @sum )
 BEGIN
  SET @sum = @sum + @bb
  ;
  INSERT INTO #tmp( aa, bb, cc, dd, cs ) VALUES( @aa, @bb, @cc, @dd, @sum )
  ;
 END
 ELSE
 BEGIN
  BREAK
  ;
 END
 FETCH NEXT FROM cur INTO @aa, @bb, @cc, @dd;
END

begin ... end 는 델파이 소스코드 아닌가요? 쿼리에서도 실행이 되는건가요?
'@aa','@sum' 변수를 선언해야 합니다. 에러납니다 한번에 맨밑줄 DROP TABLE #tmp 빼고 전체
드레그해서 실행시켜도 에러나네요 부탁드립니다...수고하세요

우성대왕짱님이 2013-01-08 12:42에 작성한 댓글입니다. Edit

 DECLARE cur CURSOR LOCAL FORWARD_ONLY FAST_FORWARD READ_ONLY

FOR
SELECT aa, bb, cc, dd FROM outm_1210
;
 
 
위의 부분을 
 
 
DECLARE cur CURSOR FAST_FORWARD
FOR
SELECT aa, bb, cc, dd FROM outm_1210
;
 
로 고치고 모두 한방에 돌려주세요.. ㅋ
 
2000을 깔아놓진 않아서 걍 2008에서 잘 돌길래.. ㅋㅋㅋ
우욱님이 2013-01-08 20:21에 작성한 댓글입니다. Edit

DECLARE @junno DATETIME;
DECLARE @tmamoney1 INT;
DECLARE @tbamoney1 INT;
DECLARE @saletime CHAR(5);
 
CREATE TABLE #tmp(junno datetime, tmamoney1 int, tbamoney1 int, saletime char(5), cs INT);
DECLARE @sum INT;
SET @sum = 0;

DECLARE cur CURSOR FAST_FORWARD FOR SELECT junno, tmamoney1, tbamoney1, saletime FROM outm_1210;

OPEN cur;

FETCH NEXT FROM cur INTO @junno, @tmamoney1, @tbamoney1, @saletime;
 
WHILE @@FETCH_STATUS = 0
BEGIN
 IF ABS( 10000 - @sum - @tmamoney1 ) < ABS( 10000 - @sum )
 BEGIN
  SET @sum = @sum + @tmamoney1;
  INSERT INTO #tmp( junno, tmamoney1, tbamoney1, saletime, cs ) VALUES( @junno, @tmamoney1, @tbamoney1, @saletimed, @sum );
 END
 ELSE
 BEGIN
  BREAK;
 END
 FETCH NEXT FROM cur INTO @junno, @tmamoney1, @tbamoney1, @saletime;
END
 
CLOSE cur;
DEALLOCATE cur;
 
SELECT junno, tmamoney1, tbamoney1, saletime, cs FROM #tmp; 한번에 실행

Server: Msg 137, Level 15, State 1, Line 9
Must declare the variable '@junno'.
Server: Msg 137, Level 15, State 1, Line 13
Must declare the variable '@tmamoney1'.
Server: Msg 137, Level 15, State 1, Line 15
Must declare the variable '@tmamoney1'.
Server: Msg 137, Level 15, State 1, Line 16
Must declare the variable '@junno'.
Server: Msg 137, Level 15, State 1, Line 22
Must declare the variable '@junno'.
 

가상 테이블 만들어서 실행하면 에러가 안나는데 실제 outm_1210 테이블에서 실행하면 에러가 납니다.

junno, day1, comcode, comname, tmoney0vat, tmamoney1, tbamoney1, tmoneydc, tmoneymg, cdmoney1, memberno, saletime,
ismagam, cardno, isbaedal, posno, manid, baedalin, week_str, cmscount, cmsmoney, ccdc, samoney1, inmoney1, mimoney1,
pointuse, totenddc, membpoint, cashback_use, VD_money1, cashuse
총31개의 실제 컬럼명 입니다...

우성대왕짱님이 2013-01-09 01:01에 작성한 댓글입니다. Edit

컬럼들의 type도 알아야 될텐데요.

우욱님이 2013-01-09 08:45에 작성한 댓글입니다. Edit

Columa_name Type Computed Length Prec Scale Nullable TrimTraillingBlanks FixedLenNullInSource Collations
junno varchar no 17             no yes no Korean_Wansung_CI_AS
day1 varchar no 10             no yes no Korean_Wansung_CI_AS
comcode varchar no 5             yes yes no Korean_Wansung_CI_AS
comname varchar no 30             yes yes no Korean_Wansung_CI_AS
tmoney0vat decimal no 9 12 2 yes (n/a) (n/a) NULL
tmamoney1 decimal no 9 12 2 yes (n/a) (n/a) NULL
tbamoney1 decimal no 9 12 2 yes (n/a) (n/a) NULL
tmoneydc decimal no 9 12 2 yes (n/a) (n/a) NULL
tmoneymg decimal no 9 12 2 yes (n/a) (n/a) NULL
cdmoney1 decimal no 9 12 2 yes (n/a) (n/a) NULL
memberno varchar no 15             yes yes no Korean_Wansung_CI_AS
saletime varchar no 5             yes yes no Korean_Wansung_CI_AS
ismagam char no 1             yes yes yes Korean_Wansung_CI_AS
cardno varchar no 20             yes yes no Korean_Wansung_CI_AS
isbaedal char no 1             yes yes yes Korean_Wansung_CI_AS
posno varchar no 2             yes no no Korean_Wansung_CI_AS
manid varchar no 10             yes yes no Korean_Wansung_CI_AS
baedalin varchar no 10             yes yes no Korean_Wansung_CI_AS
week_str varchar no 2             yes yes no Korean_Wansung_CI_AS
cmscount decimal no 9 12 2 yes (n/a) (n/a) NULL
cmsmoney decimal no 9 12 2 yes (n/a) (n/a) NULL
ccdc decimal no 9 12 2 yes (n/a) (n/a) NULL
samoney1 decimal no 9 12 2 yes (n/a) (n/a) NULL
inmoney1 decimal no 9 12 2 yes (n/a) (n/a) NULL
mimoney1 decimal no 9 12 2 yes (n/a) (n/a) NULL
pointuse decimal no 9 12 2 yes (n/a) (n/a) NULL
totenddc decimal no 9 12 2 yes (n/a) (n/a) NULL
membpoint decimal no 9 12 2 yes (n/a) (n/a) NULL
cashback_use decimal no 9 12 2 yes (n/a) (n/a) NULL
VD_money1 decimal no 9 12 2 yes (n/a) (n/a) NULL
cashuse char no 1             yes yes yes Korean_Wansung_CI_AS
 

junno,day1
--Null허용 체크없음

 

tmoney0vat,tmamoney1,tbamoney1,tmoneydc,tmoneymg,cdmoney1,cmscount,cmsmoney,ccdc,samoney1,
--데이터형식 decimal, 길이 9 인데 밑의정보란에는 전체자릿수 10, 소수자릿수 2 라고 되어있어요

 

inmoney1,mimoney1,pointuse,totenddc,membpoint,ashback_use,VD_money1,
--데이터형식 decimal, 길이 9 인데 밑의정보란에는 전체자릿수 12, 소수자릿수 2 라고 되어있어요
 

김우성(babokws)님이 2013-01-09 10:45에 작성한 댓글입니다.
이 댓글은 2013-01-09 16:46에 마지막으로 수정되었습니다.

그럼 최종버전은 이렇게 되는 걸까요? ㅋ

 

declare @junno varchar(17);

declare @day1 varchar(10);

declare @comcode varchar(5);

declare @comname varchar(30);

declare @tmoney0vat decimal(9);

declare @tmamoney1 decimal(9);

declare @tbamoney1 decimal(9);

declare @tmoneydc decimal(9);

declare @tmoneymg decimal(9);

declare @cdmoney1 decimal(9);

declare @memberno varchar(15);

declare @saletime varchar(5);

declare @ismagam char(1);

declare @cardno varchar(20);

declare @isbaedal char(1);

declare @posno varchar(2);

declare @manid varchar(10);

declare @baedalin varchar(10);

declare @week_str varchar(2);

declare @cmscount decimal(9);

declare @cmsmoney decimal(9);

declare @ccdc decimal(9);

declare @samoney1 decimal(9);

declare @inmoney1 decimal(9);

declare @mimoney1 decimal(9);

declare @pointuse decimal(9);

declare @totenddc decimal(9);

declare @membpoint decimal(9);

declare @cashback_use decimal(9);

declare @VD_money1 decimal(9);

declare @cashuse char(1);

 

CREATE TABLE #tmp(

junno varchar(17),

day1 varchar(10),

comcode varchar(5),

comname varchar(30),

tmoney0vat decimal(9),

tmamoney1 decimal(9),

tbamoney1 decimal(9),

tmoneydc decimal(9),

tmoneymg decimal(9),

cdmoney1 decimal(9),

memberno varchar(15),

saletime varchar(5),

ismagam char(1),

cardno varchar(20),

isbaedal char(1),

posno varchar(2),

manid varchar(10),

baedalin varchar(10),

week_str varchar(2),

cmscount decimal(9),

cmsmoney decimal(9),

ccdc decimal(9),

samoney1 decimal(9),

inmoney1 decimal(9),

mimoney1 decimal(9),

pointuse decimal(9),

totenddc decimal(9),

membpoint decimal(9),

cashback_use decimal(9),

VD_money1 decimal(9),

cashuse char(1)

cs decimal(9)

)

;

DECLARE @sum decimal(9)

;

SET @sum = 0

;

 

DECLARE cur CURSOR FAST_FORWARD

FOR

SELECT 

junno

, day1

, comcode

, comname

, tmoney0vat

, tmamoney1

, tbamoney1

, tmoneydc

, tmoneymg

, cdmoney1

, memberno

, saletime

, ismagam

, cardno

, isbaedal

, posno

, manid

, baedalin

, week_str

, cmscount

, cmsmoney

, ccdc

, samoney1

, inmoney1

, mimoney1

, pointuse

, totenddc

, membpoint

, cashback_use

, VD_money1

, cashuse

FROM outm_1210

;

 

OPEN cur

;

 

FETCH NEXT FROM cur INTO 

@junno

, @day1

, @comcode

, @comname

, @tmoney0vat

, @tmamoney1

, @tbamoney1

, @tmoneydc

, @tmoneymg

, @cdmoney1

, @memberno

, @saletime

, @ismagam

, @cardno

, @isbaedal

, @posno

, @manid

, @baedalin

, @week_str

, @cmscount

, @cmsmoney

, @ccdc

, @samoney1

, @inmoney1

, @mimoney1

, @pointuse

, @totenddc

, @membpoint

, @cashback_use

, @VD_money1

, @cashuse

;

 

WHILE @@FETCH_STATUS = 0

BEGIN

IF ABS( 10000 - @sum - @tmamoney1 ) < ABS( 10000 - @sum )

BEGIN

SET @sum = @sum + @tmamoney1

;

INSERT INTO #tmp

junno

, day1

, comcode

, comname

, tmoney0vat

, tmamoney1

, tbamoney1

, tmoneydc

, tmoneymg

, cdmoney1

, memberno

, saletime

, ismagam

, cardno

, isbaedal

, posno

, manid

, baedalin

, week_str

, cmscount

, cmsmoney

, ccdc

, samoney1

, inmoney1

, mimoney1

, pointuse

, totenddc

, membpoint

, cashback_use

, VD_money1

, cashuse

, cs 

VALUES

@junno

, @day1

, @comcode

, @comname

, @tmoney0vat

, @tmamoney1

, @tbamoney1

, @tmoneydc

, @tmoneymg

, @cdmoney1

, @memberno

, @saletime

, @ismagam

, @cardno

, @isbaedal

, @posno

, @manid

, @baedalin

, @week_str

, @cmscount

, @cmsmoney

, @ccdc

, @samoney1

, @inmoney1

, @mimoney1

, @pointuse

, @totenddc

, @membpoint

, @cashback_use

, @VD_money1

, @cashuse

, @sum 

)

;

END

ELSE

BEGIN

BREAK

;

END

FETCH NEXT FROM cur INTO

@junno

, @day1

, @comcode

, @comname

, @tmoney0vat

, @tmamoney1

, @tbamoney1

, @tmoneydc

, @tmoneymg

, @cdmoney1

, @memberno

, @saletime

, @ismagam

, @cardno

, @isbaedal

, @posno

, @manid

, @baedalin

, @week_str

, @cmscount

, @cmsmoney

, @ccdc

, @samoney1

, @inmoney1

, @mimoney1

, @pointuse

, @totenddc

, @membpoint

, @cashback_use

, @VD_money1

, @cashuse

;

END

 

CLOSE cur

;

DEALLOCATE cur

;

 

SELECT * FROM #tmp

;

 

DROP TABLE #tmp

;

 

우욱님이 2013-01-10 08:18에 작성한 댓글입니다. Edit

해결된줄 알았는 또다른 문제 발견됐어요...

생략...

DECLARE cur CURSOR FAST_FORWARD FOR SELECT d.scancode, d.junno, d.serial, d.day1, d.mb, d.remark, d.icomcode, d.barcode, d.tmoney0vat,
d.money1, d.money1vat1dc, d.tmamoney1, d.tbamoney1, d.mitemcount, d.bitemcount, d.tmoneydc, d.tmoneymg, d.memberno, d.saletime, d.gubun1,
d.gubun2, d.gubun3, d.ismagam, d.alpha, d.issale, d.cardvat1, d.cardvat0, d.isvat, d.posno, d.bottcode, d.bottmoney1
FROM
outd_1207 d, outm_1207 m
where d.junno=m.junno and m.cdmoney1 like '0%'and m.memberno like 'X%'and m.cashuse!='1'
and d.cardvat1 like '0%'and d.cardvat0 like '0%'and d.memberno like '-%'and d.day1 like '2012-07-01'

생략...
조건은 20,000에 가장 근사치를 구하고 싶은데 outm전표 밑의 outd전표라서 outd는 outm전표에 포함되거나 안되거나해야 되는데 위의 조건으로 하면 outd의 개수 일부가 가장근사치일때 일부가 따라 오는 문제가 생기네요 serial 개수만큼 포함이 되거나 안되거나 하는 방법이 있을까요?

outm      
cs junno day1 tmamoney1
550 2012-07-0110001 2012-07-01 550
6520 2012-07-0110004 2012-07-01 5970
21070 2012-07-0110006 2012-07-01 14550
24070 2012-07-0110007 2012-07-01 3000
37210 2012-07-0110008 2012-07-01 13140

outd          
cs scancode junno serial day1 tmamoney1
550 2012-07-01100011 2012-07-0110001 1 2012-07-01 550
3450 2012-07-01100041 2012-07-0110004 1 2012-07-01 2900
5130 2012-07-01100042 2012-07-0110004 2 2012-07-01 1680
6480 2012-07-01100043 2012-07-0110004 3 2012-07-01 1350
6520 2012-07-01100044 2012-07-0110004 4 2012-07-01 40
18520 2012-07-01100061 2012-07-0110006 1 2012-07-01 12000
20770 2012-07-01100062 2012-07-0110006 2 2012-07-01 2250
21070 2012-07-01100063 2012-07-0110006 3 2012-07-01 300
24070 2012-07-01100071 2012-07-0110007 1 2012-07-01 3000
33210 2012-07-01100081 2012-07-0110008 1 2012-07-01 9140

김우성(babokws)님이 2013-01-15 01:20에 작성한 댓글입니다.
이 댓글은 2013-01-15 05:30에 마지막으로 수정되었습니다.

 outm 테이블로 먼저 대상 주문들을 구한  결과를 가지고 outd와 join하세요.

우욱님이 2013-01-15 12:32에 작성한 댓글입니다. Edit

님의 팁 대로 select는 해결이 됐는데요...

outm 컬럼들의 값들을 *2 하고싶어요
update outm_1301 set tmamoney1*2,tbamoney1*2,tmoneydc*2,tmoneymg*2,inmoney1*2

outd outm 컬럼들의 값들도 *2 하고싶어요
update outd_1301 set tmoney0vat*2,tmamoney1*2,tbamoney1*2,mitemcount*2,tmoneymg*2,tmoneydc*2

outm전표 하나에 outd전표상세 여러 품목이 종속되어있습니다.

님이 보내주신 쿼리문은 #tmp에 select한 값이 insert되어 있는데

그결과물의 junno 전표들의 값들을 update 까지 연결이 가능한가요?
어렵더라도 방법좀 갈켜 주시면 정말정말 감사하겠습니다...복받으실겁니다...

우성대왕짱님이 2013-01-15 16:35에 작성한 댓글입니다. Edit

 UPDATE outm

set outm.컬럼 = outm.컬럼*2

, outm.커얼럼 = outm.커얼럼*2

-- 등등 필요한 update 컬럼들

FROM outm AS mm

INNER JOIN #tmp AS tt ON mm.junno = tt.junno

;

 

 UPDATE outd

set outd.컬럼 = outd.컬럼*2

, outd.커얼럼 = outd.커얼럼*2

-- 등등 필요한 update 컬럼들

FROM outd AS dd

INNER JOIN #tmp AS tt ON dd.junno = tt.junno

;

 

 

우욱님이 2013-01-15 21:37에 작성한 댓글입니다. Edit

update outm_1210 set outm_1210.tmamoney1=outm_1210.tmamoney1*2, outm_1210.inmoney1=outm_1210.inmoney1*2
from outm_1210 AS mm INNER JOIN #tmp AS tt ON mm.junno = tt.junno

#tmp 에는 outm_1210의 정보들이 있는데도...

서버: 메시지 107, 수준 16, 상태 3, 줄 1
열 접두사 'outm_1210'이(가) 쿼리에 사용된 별칭 이름이나 테이블 이름과 일치하지 않습니다.
서버: 메시지 107, 수준 16, 상태 1, 줄 1
열 접두사 'outm_1210'이(가) 쿼리에 사용된 별칭 이름이나 테이블 이름과 일치하지 않습니다.

아무리 조건 바꿔봐도 안되네요...도와주세요...

우성대왕짱님이 2013-01-15 23:22에 작성한 댓글입니다. Edit

 헛.. 실수를.. ㄷㄷ

 

2000 깔린거 없다는 핑계로 머리 속으로만 짜다보니.. T,.T

 

UPDATE outm_1210

set tmamoney1=outm_1210.tmamoney1*2

, inmoney1=outm_1210.inmoney1*2 

from outm_1210 AS mm

INNER JOIN #tmp AS tt

ON mm.junno = tt.junno

;

 

우욱님이 2013-01-16 13:35에 작성한 댓글입니다. Edit

드뎌 해결됐습니다...감사드립니다....수고하세요!

하나더 궁금한게 있는데요

backup database test to disk='c:\test'

Client 에서 명령을 주면 Server 컴에 Backup 이 됩니다.

Client에 저장 할수있는 방법이 있나요?

우성대왕짱님이 2013-01-18 21:58에 작성한 댓글입니다.
이 댓글은 2013-01-18 22:06에 마지막으로 수정되었습니다. Edit

CREATE ...생략

--날짜변경할것  2개
select m.* from outm_1110 m, outd_1110 d where m.junno=d.junno

--날짜 및 일자 변경할것 1개
 and m.cdmoney1 like '0%'and m.memberno like 'X%'and m.cashuse!='1'and m.day1 like '2011-10-01'
 and d.cardvat1 like '0%'and d.cardvat0 like '0%'and d.memberno like '-%'
group by m.junno,m.day1,m.comcode,m.comname,m.tmoney0vat,m.tmamoney1,m.tbamoney1,m.tmoneydc,m.tmoneymg,m.cdmoney1,m.memberno,
m.saletime,m.ismagam,m.cardno,m.isbaedal,m.posno,m.manid,m.baedalin,m.week_str,m.cmscount,m.cmsmoney,m.ccdc,m.samoney1,m.inmoney1,
m.mimoney1,m.pointuse,m.totenddc,m.membpoint,m.cashback_use,m.VD_money1,m.cashuse order by m.junno

--금액변경할것 2개
WHILE @@FETCH_STATUS = 0 BEGIN IF ABS( 300000 - @sum - @tmamoney1 ) < ABS( 300000 - @sum )
 BEGIN SET @sum = @sum + @tmamoney1;

--날짜변경할것 1개
update outm_1110
 set tmamoney1=m.tmamoney1*2, tbamoney1=m.tbamoney1*2, tmoneydc=m.tmoneydc*2,
 tmoneymg=m.tmoneymg*2, inmoney1=m.inmoney1*2, mimoney1=m.mimoney1*2, VD_money1=m.VD_money1*2

--날짜변경할것 1개
 from outm_1110
 as m inner join #tmp as t on m.junno=t.junno;

--날짜변경할것 1개
update outd_1110
 set tmoney0vat=d.tmoney0vat*2, tmamoney1=d.tmamoney1*2, tbamoney1=d.tbamoney1*2,
mitemcount=d.mitemcount*2, bitemcount=d.bitemcount*2, tmoneydc=d.tmoneydc*2, tmoneymg=d.tmoneymg*2

--날짜변경할것 1개
 from outd_1110
 as d inner join #tmp as t on d.junno=t.junno;

이렇게 쿼리 돌리면 '2011-10-01' 하루것만 300,000의 근사치값을 구해주는데
 

하루말고 30일 한달치를 한번에 할수 있는 방법도 있을까요?

김우성(babokws)님이 2013-01-19 21:23에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
6607합계를 구하고 싶어요... [4]
김우성
2012-12-31
7604
6597delete 문을 빠르게 하는 방법.. [1]
피크맨
2012-12-27
7853
6596index 생성시... 이거 업데이트도 따로 해 줘야 하나요? [1]
동장군
2012-12-27
7290
6595근사치 필드 까지만 select 할수 있는 쿼리좀...부탁합니다 [27]
김우성
2012-12-26
10945
6594DB 디자인 도움좀 부탁해요. 인사과. [2]
우세연
2012-12-19
7390
6592SQL server user license 질문.. [2]
코스
2012-12-17
7823
6560INSERT OPENQUERY 질문입니다.
곰보
2012-12-12
7645
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.023초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다