T-SQL subquery Max (Date) and Joins

Próbuję połączyć wiele tabel, ale jedna z tabel ma wiele rekordów dla partydu z różnymi datami. Chcę zdobyć płytę z ostatnią datą.

Oto kilka przykładowych tabel:

Table: MyParts
Partid   Partnumber   Description
1        ABC-123      Pipe
2        ABC-124      Handle
3        ABC-125      Light


Table: MyPrices
Partid   Price        PriceDate
1        $1           1/1/2005
1        $2           1/1/2007
1        $3           1/1/2009
2        $2           1/1/2005
2        $4           1/1/2006
2        $5           1/1/2008
3        $10          1/1/2008
3        $12          1/1/2009

Gdybym tylko chciał znaleźć najnowszą cenę za pewną część, którą mógłbym zrobić:

SELECT * FROM MyPrice WHERE PriceDate = (SELECT MAX(PriceDate) 
FROM MyPrice WHERE Partid = 1)

Jednak chcę najpierw wykonać połączenie i odzyskać poprawną cenę za wszystkie części, a nie tylko jedną. Tego właśnie próbowałem:

SELECT * FROM MyParts LEFT JOIN MyPrice ON MyParts.Partid = MyPrice.Partid WHERE 
MyPart.PriceDate = (SELECT MAX(PriceDate) FROM MyPrice)

Wyniki są błędne, ponieważ zajmuje najwyższą datę ceny całego stołu.

SELECT * FROM MyParts LEFT JOIN MyPrice ON MyParts.Partid = MyPrice.Partid WHERE 
MyPart.PriceDate = (SELECT MAX(PriceDate) FROM MyPrice WHERE MyPrice.Partid =   
MyParts.Partid)

To błąd.

Co mogę zrobić, aby uzyskać pożądane rezultaty.

Author: Cade Roux, 2009-05-18

10 answers

Spróbuj tego:

Select *,
    Price = (Select top 1 Price 
             From MyPrices 
             where PartID = mp.PartID 
             order by PriceDate desc
            )
from MyParts mp
 31
Author: wcm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-18 19:29:31

Oto inny sposób, aby to zrobić bez zapytań podrzędnych. Ta metoda często przewyższa inne, więc warto przetestować obie metody, aby zobaczyć, która daje najlepszą wydajność.

SELECT
     PRT.PartID,
     PRT.PartNumber,
     PRT.Description,
     PRC1.Price,
     PRC1.PriceDate
FROM
     MyParts PRT
LEFT OUTER JOIN MyPrices PRC1 ON
     PRC1.PartID = PRT.PartID
LEFT OUTER JOIN MyPrices PRC2 ON
     PRC2.PartID = PRC1.PartID AND
     PRC2.PriceDate > PRC1.PriceDate
WHERE
     PRC2.PartID IS NULL

To da wiele wyników, jeśli masz dwie ceny o tej samej dokładnej cenie (większość innych rozwiązań zrobi to samo). Ponadto, nie ma nic do uwzględnienia ostatniej daty ceny w przyszłości. Możesz rozważyć sprawdzenie tego niezależnie od tego, jakiej metody ostatecznie używasz.

 31
Author: Tom H,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-18 21:00:20

Spróbuj połączyć się z zapytaniem podrzędnym MyPrice w celu pobrania MAX(PriceDate):

SELECT a.*, MyPriceDate.Price, MyPriceDate.PriceDate
FROM MyParts a
INNER JOIN (
    SELECT Partid, MAX(PriceDate) AS MaxPriceDate 
    FROM MyPrice 
    GROUP BY Partid
) dt ON a.Partid = dt.Partid
INNER JOIN MyPrice ON dt.Partid = MyPrice.Partid 
                   AND a.PriceDate = dt.MaxPriceDate
 10
Author: KM.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-27 17:42:39

Na rok 2005 ROW_NUMBER():

SELECT * FROM 
    ( SELECT p.*,
        ROW_NUMBER() OVER(PARTITION BY Partid ORDER BY PriceDate DESC) AS rn
    FROM MyPrice AS p ) AS t
WHERE rn=1
 5
Author: A-K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-29 08:28:48

Coś takiego

SELECT * 
FROM MyParts 
LEFT JOIN 
(
SELECT MAX(PriceDate), PartID FROM MyPrice group by PartID
) myprice
 ON MyParts.Partid = MyPrice.Partid 

Jeśli znasz swoją partyd lub możesz ją ograniczyć, umieść ją wewnątrz join.

   SELECT myprice.partid, myprice.partdate, myprice2.Price, * 
    FROM MyParts 
    LEFT JOIN 
    (
    SELECT MAX(PriceDate), PartID FROM MyPrice group by PartID
    ) myprice
     ON MyParts.Partid = MyPrice.Partid 
    Inner Join MyPrice myprice2
    on myprice2.pricedate = myprice.pricedate
    and myprice2.partid = myprice.partid
 4
Author: u07ch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-18 18:55:06
SELECT
    *
FROM
    (SELECT MAX(PriceDate) AS MaxP, Partid FROM MyPrices GROUP BY Partid) MaxP 
    JOIN
    MyPrices MP On MaxP.Partid = MP.Partid AND MaxP.MaxP = MP.PriceDate
    JOIN
    MyParts P ON MP.Partid = P.Partid

Najpierw musisz pobrać najnowszy pricedate dla partid (standardowy agregat), a następnie dołączyć go z powrotem, aby uzyskać ceny (które nie mogą być w agregacie), a następnie uzyskać szczegóły części.

 2
Author: gbn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-18 18:38:08

Dołącz do tabeli cen, a następnie wybierz wpis na ostatni dzień:

select pa.partid, pa.Partnumber, max(pr.price)
from myparts pa
inner join myprices pr on pr.partid = pa.partid
where pr.PriceDate = (
    select max(PriceDate) 
    from myprices 
    where partid = pa.partid
)

Max() jest w przypadku, gdy istnieje wiele cen dziennie; zakładam, że chcesz wyświetlić najwyższą. Jeśli twoja tabela cen ma kolumnę id, możesz uniknąć max () i uprościć TAK:

select pa.partid, pa.Partnumber, pr.price
from myparts pa
inner join myprices pr on pr.partid = pa.partid
where pr.priceid = (
    select max(priceid)
    from myprices 
    where partid = pa.partid
)

P. S. użyj zamiast tego rozwiązania wcm!

 2
Author: Andomar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-18 18:49:52

Wszystkie inne odpowiedzi muszą działać, ale używając tej samej składni (i rozumiejąc, dlaczego błąd)

SELECT * FROM MyParts LEFT JOIN MyPrice ON MyParts.Partid = MyPrice.Partid WHERE 
MyPart.PriceDate = (SELECT MAX(MyPrice2.PriceDate) FROM MyPrice as MyPrice2 
WHERE MyPrice2.Partid =  MyParts.Partid)
 1
Author: Eduardo Molteni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-18 18:45:11

Wypróbuj następny przykład kodu:

select t1.*, t2.partprice, t2.partdate 
from myparts t1
join myprices t2 
on t1.partid = t2.partid
where partdate = 
(select max(partdate) from myprices t3 
where t3.partid = t2.partid group by partid)
 0
Author: Rupal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-08 08:08:24

Dla MySQL, proszę znaleźć poniższe zapytanie:

select * from (select PartID, max(Pricedate) max_pricedate from MyPrices group bu partid) as a 
    inner join MyParts b on
    (a.partid = b.partid and a.max_pricedate = b.pricedate)

Wewnątrz subquery pobiera max pricedate dla każdej partyid MyPrices następnie, połączenie wewnętrzne z MyParts za pomocą partid i max_pricedate

 0
Author: Suren,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-25 00:36:29