첫 번째 줄에 가입하는 방법
구체적인 예를 들겠습니다만, 하지만 가정적인 예를 들겠습니다.
각 주문에는 보통 한 줄의 항목만 포함됩니다.
주문:
OrderGUID OrderNumber
========= ============
{FFB2...} STL-7442-1
{3EC6...} MPT-9931-8A
라인 항목:
LineItemGUID Order ID Quantity Description
============ ======== ======== =================================
{098FBE3...} 1 7 prefabulated amulite
{1609B09...} 2 32 spurving bearing
단, 두 줄의 아이템이 포함된 주문이 있을 수 있습니다.
LineItemID Order ID Quantity Description
========== ======== ======== =================================
{A58A1...} 6,784,329 5 pentametric fan
{0E9BC...} 6,784,329 5 differential girdlespring
일반적으로 사용자에게 주문을 표시할 때:
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
INNER JOIN LineItems
ON Orders.OrderID = LineItems.OrderID
주문하신 상품을 1개만 보여드리고 싶습니다.그러나 이 주문에는 2개 이상의 아이템이 포함되어 있기 때문에 주문이 중복되어 표시됩니다.
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 spurving bearing
KSG-0619-81 5 panametric fan
KSG-0619-81 5 differential girdlespring
SQL Server는 다음 중 하나를 선택하기만 하면 됩니다.
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 differential girdlespring
KSG-0619-81 5 panametric fan
모험심을 갖게 되면 사용자에게 줄임표를 보여 줄 수 있습니다.
OrderNumber Quantity Description
=========== ======== ====================
STL-7442-1 7 prefabulated amulite
MPT-9931-8A 32 differential girdlespring
KSG-0619-81 5 panametric fan, ...
그래서 문제는 어떻게 하면
- '경고' 행을 삭제하다
- 중복을 피하기 위해 행 중 하나에만 결합합니다.
첫 번째 시도
저의 첫 번째 순진한 시도는 "TOP 1" 라인의 항목에만 참여하는 것이었습니다.
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
INNER JOIN (
SELECT TOP 1 LineItems.Quantity, LineItems.Description
FROM LineItems
WHERE LineItems.OrderID = Orders.OrderID) LineItems2
ON 1=1
하지만 그 결과 다음과 같은 오류가 발생합니다.
'Orders' 열 또는 접두사는
테이블명 또는 에일리어스명과 일치하다
쿼리에서 사용됩니다.
아마도 내부 선택에서 외부 테이블을 볼 수 없기 때문일 것입니다.
SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description
FROM Orders
JOIN LineItems
ON LineItems.LineItemGUID =
(
SELECT TOP 1 LineItemGUID
FROM LineItems
WHERE OrderID = Orders.OrderID
)
SQL Server 2005 이상에서는 다음 명령어를 대체할 수 있습니다.INNER JOIN
와 함께CROSS APPLY
:
SELECT Orders.OrderNumber, LineItems2.Quantity, LineItems2.Description
FROM Orders
CROSS APPLY
(
SELECT TOP 1 LineItems.Quantity, LineItems.Description
FROM LineItems
WHERE LineItems.OrderID = Orders.OrderID
) LineItems2
주의하시기 바랍니다.TOP 1
없이.ORDER BY
이 쿼리는 확정적이지 않습니다.이 쿼리는 주문당 한 줄의 아이템을 얻을 수 있지만 어떤 아이템이 될지는 정의되어 있지 않습니다.
쿼리를 여러 번 호출하면 기본 항목이 변경되지 않았더라도 동일한 순서에 대해 서로 다른 행 항목을 제공할 수 있습니다.
결정론적 순서를 원할 경우 다음 순서를 추가해야 합니다.ORDER BY
가장 안쪽 쿼리에 대한 절입니다.
조금 전에 이 질문에 답한 것은 알고 있습니다만, 대량의 데이터 세트를 취급할 때는, 네스트 된 쿼리에 코스트가 드는 경우가 있습니다.다음은 반환되는 각 행이 아닌 중첩된 쿼리를 한 번만 실행하는 다른 솔루션입니다.
SELECT
Orders.OrderNumber,
LineItems.Quantity,
LineItems.Description
FROM
Orders
INNER JOIN (
SELECT
Orders.OrderNumber,
Max(LineItem.LineItemID) AS LineItemID
FROM
Orders INNER JOIN LineItems
ON Orders.OrderNumber = LineItems.OrderNumber
GROUP BY Orders.OrderNumber
) AS Items ON Orders.OrderNumber = Items.OrderNumber
INNER JOIN LineItems
ON Items.LineItemID = LineItems.LineItemID
@Quassnoi 답변이 좋습니다.경우에 따라서는 (특히 바깥쪽 테이블이 큰 경우) 다음과 같은 윈도우 함수를 사용하는 것이 더 효율적입니다.
SELECT Orders.OrderNumber, LineItems2.Quantity, LineItems2.Description
FROM Orders
LEFT JOIN
(
SELECT LineItems.Quantity, LineItems.Description, OrderId, ROW_NUMBER()
OVER (PARTITION BY OrderId ORDER BY (SELECT NULL)) AS RowNum
FROM LineItems
) LineItems2 ON LineItems2.OrderId = Orders.OrderID And RowNum = 1
경우에 따라서는 어떤 쿼리가 더 나은 성능을 제공하는지만 테스트해야 할 수도 있습니다.
다음과 같은 작업을 할 수 있습니다.
SELECT
Orders.OrderNumber,
LineItems.Quantity,
LineItems.Description
FROM
Orders INNER JOIN LineItems
ON Orders.OrderID = LineItems.OrderID
WHERE
LineItems.LineItemID = (
SELECT MIN(LineItemID)
FROM LineItems
WHERE OrderID = Orders.OrderID
)
여기에는 다음 위치에 인덱스(또는 기본 키)가 필요합니다.LineItems.LineItemID
및 에 대한 색인LineItems.OrderID
안 그러면 느려요.
SQL Server 2012 이후로는 다음과 같은 이점을 얻을 수 있을 것입니다.
SELECT DISTINCT
o.OrderNumber ,
FIRST_VALUE(li.Quantity) OVER ( PARTITION BY o.OrderNumber ORDER BY li.Description ) AS Quantity ,
FIRST_VALUE(li.Description) OVER ( PARTITION BY o.OrderNumber ORDER BY li.Description ) AS Description
FROM Orders AS o
INNER JOIN LineItems AS li ON o.OrderID = li.OrderID
, 공통 테이블 표현을 사용하는 다른 aproach:
with firstOnly as (
select Orders.OrderNumber, LineItems.Quantity, LineItems.Description, ROW_NUMBER() over (partiton by Orders.OrderID order by Orders.OrderID) lp
FROM Orders
join LineItems on Orders.OrderID = LineItems.OrderID
) select *
from firstOnly
where lp = 1
아니면 마지막으로 모든 행이 결합된 것을 보여 줄 수 있습니까?
쉼표로 구분된 버전은 다음과 같습니다.
select *
from Orders o
cross apply (
select CAST((select l.Description + ','
from LineItems l
where l.OrderID = s.OrderID
for xml path('')) as nvarchar(max)) l
) lines
상관된 하위 쿼리는 외부 쿼리에 따라 달라지는 하위 쿼리입니다.SQL의 for 루프와 같습니다.하위 쿼리는 외부 쿼리의 각 행에 대해 한 번 실행됩니다.
select * from users join widgets on widgets.id = (
select id from widgets
where widgets.user_id = users.id
order by created_at desc
limit 1
)
이 쿼리를 실행하는 가장 좋은 방법은 존재하지 않는 절을 사용하는 것입니다.저는 이것이 이런 종류의 쿼리를 실행하는 가장 효율적인 방법이라고 생각합니다.
select o.OrderNumber,
li.Quantity,
li.Description
from Orders as o
inner join LineItems as li
on li.OrderID = o.OrderID
where not exists (
select 1
from LineItems as li_later
where li_later.OrderID = o.OrderID
and li_later.LineItemGUID > li.LineItemGUID
)
그러나 나는 이 방법을 여기에 제시된 다른 방법과 비교해서 테스트하지 않았다.
됐어, 콰스누이가 더 좋은 대답을 했어.
SQL2000의 경우 다음과 같습니다.
SELECT
Orders.OrderNumber
, LineItems.Quantity
, LineItems.Description
FROM (
SELECT
Orders.OrderID
, Orders.OrderNumber
, FirstLineItemID = (
SELECT TOP 1 LineItemID
FROM LineItems
WHERE LineItems.OrderID = Orders.OrderID
ORDER BY LineItemID -- or whatever else
)
FROM Orders
) Orders
JOIN LineItems
ON LineItems.OrderID = Orders.OrderID
AND LineItems.LineItemID = Orders.FirstLineItemID
십자가를 긋고, 잘 작동하지만, 조금 더 오래 걸립니다.최대값과 추가된 그룹이 속도를 유지하고 추가 레코드를 드롭하도록 라인 열을 조정했습니다.
다음은 조정된 쿼리입니다.
SELECT Orders.OrderNumber, max(LineItems.Quantity), max(LineItems.Description)
FROM Orders
INNER JOIN LineItems
ON Orders.OrderID = LineItems.OrderID
Group by Orders.OrderNumber
언급URL : https://stackoverflow.com/questions/2043259/how-to-join-to-first-row
'source' 카테고리의 다른 글
비프라이머리 키에 대한 외부 키 (0) | 2023.04.07 |
---|---|
SQL - 문자열을 검색하는 동안 대/소문자 무시 (0) | 2023.04.07 |
SQL Server 트랜잭션의 올바른 사용 (0) | 2023.04.07 |
SQL Server에서 테이블 이름을 변경하는 방법 (0) | 2023.04.07 |
SQL Server에서 날짜/시간을 자르는 방법은 무엇입니까? (0) | 2023.04.07 |