복붙노트

[SQL] SQL 쿼리 최신 가격을 얻으려면

SQL

SQL 쿼리 최신 가격을 얻으려면

나는 MS SQL 2005 테이블에 서로 다른 "것을"많은 가격을 포함하는 테이블이 있습니다. 이 하루에 일 당 기록의 수백이고 여러 가지 다른 시간에 가격 업데이트를 가져옵니다.

ID uniqueidentifier not null,
ThingID int NOT NULL,
PriceDateTime datetime NOT NULL,
Price decimal(18,4) NOT NULL

나는 사물의 그룹에 대한 오늘날의 최신 가격을 얻을 필요가있다. 쿼리 작동하지만 내가 행의 수백을 받고 있어요 아래는 백업하고 내가 가진 그들 저점 루프 만 ThingID 당 최신의 압축을 풉니 다. 어떻게 (예를 들어를 통해 GROUP BY는) 내가 ThingID 당 최신 하나를 원하는 것을 말할 수 있습니까? 아니면 내가 서브 쿼리를 사용해야합니다?

SELECT * 
FROM Thing
WHERE ThingID IN (1,2,3,4,5,6)
  AND PriceDate > cast( convert(varchar(20), getdate(), 106) as DateTime) 

업데이트 : 나는 int 형의 ID 열을 넣어 숨기기 복잡성에 시도합니다. 현실에서 그것은 GUID (그리고 순차적 종류)입니다. 나는 고유 식별자 사용 데프 위의 표를 업데이트했습니다.

해결법

  1. ==============================

    1.나는 당신의 테이블 구조를 가진 유일한 해결책은 하위 쿼리와 함께 작동하도록 생각 :

    나는 당신의 테이블 구조를 가진 유일한 해결책은 하위 쿼리와 함께 작동하도록 생각 :

    SELECT *
       FROM Thing
       WHERE ID IN (SELECT max(ID) FROM Thing 
                       WHERE ThingID IN (1,2,3,4)
                       GROUP BY ThingID)
    

    (감안할 때 가장 높은 ID는 최신 가격을 의미한다)

    그러나 나는 그것이 최신하는 경우는, 최신 가격이나 1이 아니라면 0을하는 "대해 IsCurrent"열을 추가하는 것이 좋습니다. 이 일치하지 않는 데이터의 가능한 위험을 추가하지만, 테이블이 더 큰 얻을 때 (이 인덱스에있는 경우)는 전체 프로세스의 속도를합니다. 그런 다음 당신이 오직 할 필요가있는 것입니다 ...

    SELECT *
       FROM Thing
       WHERE ThingID IN (1,2,3,4)
         AND IsCurrent = 1
    

    최신 정보

    좋아, 마르쿠스는 ID가가 UniqueID, int가 아닌 것을 보여주기 위해 질문을 업데이트했습니다. 그것은 훨씬 더 복잡한 쿼리를 작성합니다.

    SELECT T.* 
       FROM Thing T
       JOIN (SELECT ThingID, max(PriceDateTime)
                WHERE ThingID IN (1,2,3,4)
                GROUP BY ThingID) X ON X.ThingID = T.ThingID 
                                    AND X.PriceDateTime = T.PriceDateTime
       WHERE ThingID IN (1,2,3,4)
    

    난 정말 중 하나 "대해 IsCurrent"열을 사용하거나 다른 제안에 대한 답변 및 사용 "현재 가격"테이블 궁극적으로 가장 빠른 것 별도의 "주가 추이"테이블 (발견과 가격을 유지하기 때문에, 이동 좋을 것 테이블 자체를 작은).

    (필자는 바닥에 ThingID이 중복 것을 알고있다. 그냥 함께 또는없이 빠른한다면, 시도 그 "WHERE". 확실하지 최적화 프로그램이 작업을 한 후 빠르다 버전.)

  2. ==============================

    2.나는 다음과 같은 하위 쿼리 같은 것을 시도하고 데이터 구조를 변경 잊어 것이다.

    나는 다음과 같은 하위 쿼리 같은 것을 시도하고 데이터 구조를 변경 잊어 것이다.

    SELECT
     *
    FROM
     Thing
    WHERE 
     (ThingID, PriceDateTime) IN 
     (SELECT 
       ThingID, 
       max(PriceDateTime ) 
      FROM 
       Thing 
      WHERE 
       ThingID IN (1,2,3,4)
      GROUP BY 
       ThingID
     )
    

    편집 위 ANSI SQL입니다 그리고 난 지금 T SQL에 대한 하위 쿼리 나던 작업에 하나 개 이상의 열을 가진 같은데요. 마리우스, 나는 다음을 테스트하지만 시도 할 수 없습니다

    SELECT
     p.*
    FROM
     Thing p,
     (SELECT ThingID, max(PriceDateTime ) FROM Thing WHERE ThingID IN (1,2,3,4) GROUP BY ThingID) m
    WHERE 
     p.ThingId = m.ThingId
     and p.PriceDateTime = m.PriceDateTime
    

    당신은 하나의 열이 때문에 또 다른 옵션은 ID로 문자열과 연결하는 날짜를 변경할 수 있습니다. 하지만 이것은 약간 불쾌한 것이다.

  3. ==============================

    3.서브 쿼리 경로도 나는 감사 로그로 가격 업데이트를 치료하고 ThingPrice 테이블을 유지 보는 것 저하 된 경우 - 아마도 가격 업데이트 테이블에 트리거로 :

    서브 쿼리 경로도 나는 감사 로그로 가격 업데이트를 치료하고 ThingPrice 테이블을 유지 보는 것 저하 된 경우 - 아마도 가격 업데이트 테이블에 트리거로 :

    ThingID int not null,
    UpdateID int not null,
    PriceDateTime datetime not null,
    Price decimal(18,4) not null
    

    기본 키는 ThingID과 "을 UpdateID는"원래 테이블의 "ID"입니다 것입니다.

  4. ==============================

    4.절을 적용 | 당신은 SQL 서버 2005을 사용하고 있기 때문에, 새 (OUTER CROSS)를 사용할 수 있습니다. FROM 절을하자 당신이 테이블 반환 함수와 테이블을 조인의 적용.

    절을 적용 | 당신은 SQL 서버 2005을 사용하고 있기 때문에, 새 (OUTER CROSS)를 사용할 수 있습니다. FROM 절을하자 당신이 테이블 반환 함수와 테이블을 조인의 적용.

    이 문제를 해결하려면 먼저 특정 ID에 대한 것은에서 상위 N 행을 검색 반환 함수 테이블을 정의, 날짜 순서 :

    CREATE FUNCTION dbo.fn_GetTopThings(@ThingID AS GUID, @n AS INT)
      RETURNS TABLE
    AS
    RETURN
      SELECT TOP(@n) *
      FROM Things
      WHERE ThingID= @ThingID
      ORDER BY PriceDateTime DESC
    GO
    

    다음 쿼리에서 상위 1 레코드를 검색하는 기능을 사용 :

    SELECT *
       FROM Thing t
    CROSS APPLY dbo.fn_GetTopThings(t.ThingID, 1)
    WHERE t.ThingID IN (1,2,3,4,5,6)
    

    (가) 다음 왼쪽 결과 집합의 모든 행에 함수를 적용 함수에 의해 반환 된 결과 집합을 조인 절을 적용 여기에 의해 수행되는 마법은 최종 결과 세트를 retuns. (참고 : 왼쪽을에 적용처럼 CROSS이 오른쪽에서 일치를 행만 반환을 적용하면서, 사용 outter는이, 왼쪽에서 모든 행을 반환 적용에 가입)

    연기하는거야 : 내가 게시하지 댓글이 아직 ^^ 심지어 내 자신의 대답에 (이 낮아 REPT 포인트)를 할 수 있기 때문에, 나는 메시지의 본문에 답변 해 드리겠습니다 : 그것이이 왼쪽 결과 집합의 모든 행에 대해 함수를 호출하지 않는 방식으로 SQL Server에서 내부적으로 최적화되어 테이블 반환 함수를 사용하지만, 대신 함수에서 내부 SQL을 소요하는 경우 -THE, 심지어 절을 적용 로 변환이 하위 쿼리를 사용하여 쿼리)의 성능보다 (계획이 바로 SQL 서버에 의해 선택되고 더 최적화 할 수있는 경우) 성능이 더 나은 동등 정도, 쿼리의 나머지 조항에 참여하고있는 데이터베이스가 제대로 인덱싱 및 통계 (바로 그러한 조건에서 하위 쿼리의 동작합니다와 일반 쿼리 등)를 최신 상태로있는 경우 내 개인적인 경험 적용은 성능에 문제가 없습니다

  5. ==============================

    5.그것은 당신의 데이터가 사용되는 방법의 특성에 따라 다르지만, 이전 가격 데이터는 현재 가격 데이터로 거의 정기적으로 사용하지 않을 경우, 가격 이력 테이블 여기를 인수있을 수 있습니다. 이 방법은, 비유동 데이터는 새로운 가격에 와서 (아마 트리거에 의해) 주가 추이 테이블에 떨어져 보관 할 수있다.

    그것은 당신의 데이터가 사용되는 방법의 특성에 따라 다르지만, 이전 가격 데이터는 현재 가격 데이터로 거의 정기적으로 사용하지 않을 경우, 가격 이력 테이블 여기를 인수있을 수 있습니다. 이 방법은, 비유동 데이터는 새로운 가격에 와서 (아마 트리거에 의해) 주가 추이 테이블에 떨어져 보관 할 수있다.

    내가 말하는 것처럼, 액세스 모델에 따라이 옵션이 될 수 있습니다.

  6. ==============================

    6.나는 그것의 MAX를 얻을 수 있도록 내가 바이너리에 고유 식별자를 변환하고 있습니다. 이것은 당신이 동일한 ThingIDs와 PriceDateTimes와 여러 레코드에서 중복을받지 않습니다 있는지 확인해야합니다 :

    나는 그것의 MAX를 얻을 수 있도록 내가 바이너리에 고유 식별자를 변환하고 있습니다. 이것은 당신이 동일한 ThingIDs와 PriceDateTimes와 여러 레코드에서 중복을받지 않습니다 있는지 확인해야합니다 :

    SELECT * FROM Thing WHERE CONVERT(BINARY(16),Thing.ID) IN
    (
     SELECT MAX(CONVERT(BINARY(16),Thing.ID))
      FROM Thing
      INNER JOIN
       (SELECT ThingID, MAX(PriceDateTime) LatestPriceDateTime FROM Thing
        WHERE PriceDateTime >= CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)
        GROUP BY ThingID) LatestPrices
      ON Thing.ThingID = LatestPrices.ThingID
       AND Thing.PriceDateTime = LatestPrices.LatestPriceDateTime
     GROUP BY Thing.ThingID, Thing.PriceDateTime
    ) AND Thing.ThingID IN (1,2,3,4,5,6)
    
  7. ==============================

    7.ID가 순차적 아니기 때문에, 그래서 하나 개의 가격이 특정 항목에 대한 가장 최근의 일 수있다 당신이 ThingID 및 PriceDateTime에 고유 인덱스가 있다고 가정합니다.

    ID가 순차적 아니기 때문에, 그래서 하나 개의 가격이 특정 항목에 대한 가장 최근의 일 수있다 당신이 ThingID 및 PriceDateTime에 고유 인덱스가 있다고 가정합니다.

    그들이 오늘 가격 인 경우이 쿼리는 목록에있는 모든 항목을 얻을 것이다. 당신이 PriceDate의 경우 절을 제거하면 당신은 날짜와 관계없이 최신 가격을 얻을 것이다.

    SELECT * 
    FROM Thing thi
    WHERE thi.ThingID IN (1,2,3,4,5,6)
      AND thi.PriceDateTime =
         (SELECT MAX(maxThi.PriceDateTime)
          FROM Thing maxThi
          WHERE maxThi.PriceDateTime >= CAST( CONVERT(varchar(20), GETDATE(), 106) AS DateTime)
            AND maxThi.ThingID = thi.ThingID)
    

    당신은 하루의 시작 가격 권리를 가질 수 있기 때문에 내가 "> ="에 ">"로 변경합니다

  8. ==============================

    8.이 (제공 당신은 최신 가격을 필요로하지 않는 식별자 또는 그 가격의 날짜를) 시도

    이 (제공 당신은 최신 가격을 필요로하지 않는 식별자 또는 그 가격의 날짜를) 시도

    SELECT ThingID, (SELECT TOP 1 Price FROM Thing WHERE ThingID = T.ThingID ORDER BY PriceDateTime DESC) Price
    FROM Thing T
    WHERE ThingID IN (1,2,3,4) AND DATEDIFF(D, PriceDateTime, GETDATE()) = 0
    GROUP BY ThingID
    
  9. ==============================

    9.그것은 (예를 들어 복합 기본 키에 대한) 글로벌 PK 컬럼을 사용하지 않고 일해야한다 :

    그것은 (예를 들어 복합 기본 키에 대한) 글로벌 PK 컬럼을 사용하지 않고 일해야한다 :

    SELECT t1.*, t2.PriceDateTime AS bigger FROM Prices t1 
    LEFT JOIN Prices t2 ON t1.ThingID = t2.ThingID AND t1.PriceDateTime < t2.PriceDateTime 
    HAVING t2.PriceDateTime IS NULL
    
  10. ==============================

    10.어쩌면 내가 약 작업하지만 오해 :

    어쩌면 내가 약 작업하지만 오해 :

    SELECT ID, ThingID, 최대 (PriceDateTime), 가격 것 GROUP BY ThingID FROM

  11. from https://stackoverflow.com/questions/49404/sql-query-to-get-latest-price by cc-by-sa and MIT license