2012-02-27 3 views
2

나는 혼란스러운 SQL 문제를 가지고있다. 나에게 있어도 복합 키를 반환하는 파생 쿼리로 해결할 수는 없지만 다른 필드에서는 MIN() 집계 함수를 수행한다. 표. MIN()을 복합 키 중 하나에서 수행하면 쉬울 것입니다. 그러나 양쪽 키를 반환하고 MIN() 함수를 외부 쿼리에 수행해야하므로이 작업을 수행 할 수 없습니다 . 전체 쿼리는 다음과 같습니다SQL 복합 키 그룹화 문제

SELECT 
    p.name as productname 
    ,tmp.packageid 
    ,tmp.price 
    ,ppk2.packageoptionid 
    ,ppk2.selcomproductid 
FROM ( 
     SELECT ppk.productid, ppk.packageid, MIN(ppk.price) as price 
     FROM product_package ppk 
       INNER JOIN package pk ON ppk.packageid = pk.id 
       INNER JOIN [plan] pl ON pk.planid = pl.id 
     WHERE pk.networkid = 1 
     GROUP BY ppk.productid, ppk.packageid 
) tmp 
INNER JOIN product_package ppk2 ON ( 
     ppk2.productid = tmp.productid 
    AND ppk2.packageid = tmp.packageid 
)  
INNER JOIN product p ON (p.id = ppk2.productid) 
WHERE p.isenabled = 1; 

현재 결과 :

-------------------------------------- 
productid | packageid | price 
1    500    0 
1    501    19.95 
1    502    29.95 
2    501    0 
3    500    15  
3    504    39.95 

원하는 결과

-------------------------------------- 
productid | packageid | price 
1    500    0 
2    501    0 
3    500    15 

내가 독특한 필요에 따라 내 문제가 자리하고있는 곳 파생 된 쿼리는 "TMP"입니다 외부 테이블에 조인하기 전에 가장 낮은 가격으로 각 제품/패키지 조합에 대한 행을 반환하십시오.

도움이 될 것입니다.

+0

좋은 질문입니다. 이제 : [pastebin 계정] (http://pastebin.com/)에 가입하여 stackoverflow가 코드 주위에 놓이는 추악한 슬라이더 막대를 볼 필요가 없습니까? ':)' – Droogans

+1

@Droogans 또는 코드 형식을 지정할 수 있습니다. – ninesided

+0

@nidesided : Touche, good sir. – Droogans

답변

1

글쎄, 나는 당신이 당신의 테이블에 실제로 가지고있는 데이터를 모른다. 쿼리 결과가 반환됩니다. 당신은 당신이 사용하고 있던 DBMS와 당신의 테이블의 데이터 샘플을 요구하는 나의 코멘트에 답하지 않았다.

그러나, 테이블의 현재 데이터를 가정하면 쿼리에서 나오는 하나, 다음 쿼리는 당신에게 "원하는 결과를"줄 것이다 당신이 지정한 :

테이블 즉
select t1.* from t t1 
left join t t2 
on t1.productid = t2.productid and t1.details > t2.details 
where t2.details is null 

, 이 속으로

+-----------+-----------+---------+ 
| PRODUCTID | PACKAGEID | DETAILS | 
+-----------+-----------+---------+ 
|   1 |  500 |  0 | 
|   1 |  501 |  20 | 
|   1 |  502 |  30 | 
|   2 |  501 |  0 | 
|   3 |  500 |  15 | 
|   3 |  504 |  40 | 
+-----------+-----------+---------+ 

: 쿼리는이 켜지는 분명 경우

+-----------+-----------+---------+ 
| PRODUCTID | PACKAGEID | DETAILS | 
+-----------+-----------+---------+ 
|   1 |  500 |  0 | 
|   2 |  501 |  0 | 
|   3 |  500 |  15 | 
+-----------+-----------+---------+ 

은 알려주세요 아닙니다.

+2

고마워 Mosty는 MIN() 함수를 구현하는 흥미로운 방법이며 분명히 훨씬 더 오래 기다려야 만 분명히 특정 분야에서 가장 낮은 점수를 받는다. 복합 키를 반환해야 할 때 MIN() 집계와 함께 둘 이상의 값을 반환 할 수있는 SQL Server 솔루션이 없다고 생각합니다. 당신의 도움을 주셔서 감사합니다! –

1

쉬운 방법 (읽기 : 비싼) 방법 : 두 가지보기를 작성하십시오.(각각 productid WHERE pk.networkid = 1) 및 그룹 (productid)을 만듭니다. 그것을 Product_MinPrice_VIEW 또는 무엇이든이라고 부르십시오.

는 방금 만든 Product_MinPrice_VIEW의 결과에 INNER JOIN을 통해 멀리와 얻기 위해 노력하고 모든 하위 SELECT INNER JOIN 작업을 대체하는 두 번째보기 Product_VIEW을 구축 할 수 있습니다.

맹세코, SELECTS, HAVINGSGROUP-BY과 번개는 지루하고 오류가 발생하기 쉽습니다. 나는 때때로 그것을 참을 수 없다. 다행히도, 이것은 나중에 최적화되고 더 정확한 솔루션을 개발하기에 충분할 것입니다. (나는 더 나은 대답이 사이트의 최대 히트하면서) 응용 프로그램과

최종 답변

I have an extremely similar problem 내가 작업, 평균 시간에있어, 난 그냥 벅을 통과, 일부 응용 프로그램 레벨을 썼다 중복을 다루기위한 코드, 그리고 프로그램 로직이 마주 칠 때 참된 최소값을 찾도록하십시오. 예쁘지는 않지만, 다시 한번 하루 종일 노력할 필요가 없습니다!

내 대답이 도움이되지 못해 죄송합니다. 행운을 빕니다!

+0

안녕하세요, Droogan이 응답 해 주셔서 감사합니다. 문제는 최소 packageid가 아니며 행에 영향을 미치는 최소 가격입니다. 따라서 제품에 여러 개의 패키지가있는 경우 최저 가격의 패키지 만 반환하십시오. 하지만 catch는 productid/packageid가 반환되어 테이블에 고유 한 조인을 수행하여 추가 데이터를 얻습니다. 나는 group bys와 sub-select가 특히 나무 위로 여러 열을 반환해야하고 여러 집계 함수가 관련되어있을 때 고통 스럽다는 것에 동의한다. S –

+0

아, 그때 내 대답을 업데이트 하겠지만 문제가있는 곳을 볼 수있다. . 내 해결책은'packageid'를 완전히 없애는 것이고, 그것은 진정한 대답의 데이터를 모호하게 만들 수 있습니다. 나는 이것을 더 공부해야 할 것이다. – Droogans

+0

정확히 우리가 Droggans 문제를 겪고있는 곳인데, 우리는 packageid를 없애고 행복하게 productid와 가장 낮은 가격을 되 찾을 수 있습니다. 그런 다음 더 많은 데이터에 액세스하기 위해 해당 테이블로 다시 링크 할 수있는 능력을 상실합니다. 처음에는 모든 데이터를 다시 가져 왔지만 이것은 MIN (가격) 및 GROUP BY와는 가능하지 않으며 3 단계의 파생 쿼리를 성공하지 못했습니다. 과거에 비슷한 문제가 떠돌 았던 기억을 떠올리게하기 때문에 이런 유형의 문제에 대한 좋은 해결책을 찾지 못했습니다. –

2

내가 가장 작은 쿼리와 함께 하위 쿼리가 필요할 때마다이 트릭을 사용했습니다. 이 아이디어는 값과 키를 최상위 비트의 값과 결합하여 그 중 가장 작은 부분을 차지하는 것입니다. 그런 다음 외부 선택에서 분리하십시오.

값을 결합하는 가장 좋은 방법은 사용중인 RDBMS에 따라 다릅니다. 당신은 당신이 그냥 의사 코드를 제공하고있어 지금 사용중인 하나 언급하지 않습니다

select ..., (tmp.c >> 32) price 
from 
(select productid, min((price << 32) | packageid) c 
    from product_package 
    where networkid=1 
    group by productid) tmp 
inner join product_package ppk on ppk.productid=tmp.productid 
    and ppk.packageid=(tmp.c & 0xFFFFFFFF) 
inner join product p on p.id=ppk.productid 
where p.isenabled=1 

<< 32 수단은 왼쪽에 값 32 비트를 이동하고 |는 비트 "또는"입니다. 이것은 packageid가 32 비트 정수 (또는 숫자 (4))로 정의되었다고 가정합니다. & 0xFFFFFFFF은 bitwise "and"이며 32 비트의 16 진수 값은 packageid 만 마스크하여 반환합니다.

이러한 것들에 대한 또는 당신이 일반 수학을 사용할 수 있습니다 지원되지 않습니다하는 경우 그 특정 구문을 찾을 필요가 당신의 RDBMS에 있습니다 따라 - << 32는 4294967296.로 나누어에 4294967296 및 & 0xFFFFFFFF 곱에 해당 당신이 만약 MSSQL을 사용하는 경우 convert(binary,price)+convert(binary,packageid)을 사용하여 결합하고 substring(..)을 사용하여 분리 할 수 ​​있습니다.

+0

Gordy 덕분에 또 다른 흥미로운 대답이되었습니다. MIN (가격) 및 packageid와 함께 비슷한 것을 시도했지만 너무 추한 것입니다. 귀하의 방법은 더 우아하고 나는이 시나리오에서 수학을 사용하는 것을 생각하지 않았습니다. –

+0

@ PhilRasmussen : 쿼리의 추함을 어떻게 측정 할 것인가에 달려 있다고 생각합니다. 나는이 접근법의 실행 계획과 당신이 받아 들인 답안의 실행 계획을 비교할 것을 제안합니다. 정말 멋지게 만들려면 두 개의 매개 변수를 사용하는 Min에 대한 사용자 정의 집계를 작성할 수 있습니다. – gordy