选择最后一条记录上分组依据的整行



我试图只从group by中选择last,但每次都失败了。

使用此查询:

SELECT
s.NABAVNACENA, s.ROBAID, MAX(d.DATUM) AS DATUM
FROM 
DOKUMENT d
LEFT OUTER JOIN 
STAVKA s ON s.VRDOK = d.VRDOK AND s.BRDOK = d.BRDOK
WHERE
d.VRDOK IN (0, 11, 18, 16, 22, 1, 2, 26, 29, 30)
AND d.DATUM >= '01.01.2021'
AND d.DATUM <= '31.12.2021'
AND s.ROBAID IN (39, 34)
GROUP BY 
s.ROBAID, s.NABAVNACENA

我得到这些结果

NABAVNACENA   ROBAID   DATUM
---------------------------------
149           39       01.01.2021
130           39       03.01.2021
137           39       08.01.2021
847           34       02.01.2021
820           34       03.01.2021

然而,所需的结果仅为按具有最大日期的ROBAID分组的两行。

在这种情况下:

137     39    08.01.2021
820     34    03.01.2021

当我从查询中排除s.NABAVNACENA时,它只返回这两行,但当我包含它时,它显示了所有内容。

我从Stack Overflow尝试了很多东西,但我记不清了,现在我不知道该怎么办。

这是的表格结构

/* Table: STAVKA, Owner: SYSDBA */
CREATE TABLE "STAVKA" 
(
"STAVKAID"   INTEGER NOT NULL,
"VRDOK"      SMALLINT NOT NULL,
"BRDOK"      INTEGER NOT NULL,
"MAGACINID"  SMALLINT NOT NULL,
"ROBAID"       INTEGER NOT NULL,
"VRSTA"        SMALLINT,
"NAZIV"        VARCHAR(200),
"NABCENSAPOR"  NUMERIC(15,4),
"FAKTURNACENA" NUMERIC(15,4),
"NABCENABT"    DOUBLE PRECISION,
"TROSKOVI"     NUMERIC(15,4),
"NABAVNACENA"  NUMERIC(15,4) NOT NULL,
"PRODCENABP"   NUMERIC(15,4) NOT NULL,
"KOREKCIJA"    DOUBLE PRECISION,
"PRODAJNACENA" NUMERIC(15,2) NOT NULL,
"DEVIZNACENA"  NUMERIC(15,4) NOT NULL,
"DEVPRODCENA"  NUMERIC(15,4),
"KOLICINA"     NUMERIC(15,3) NOT NULL,
"NIVKOL"       NUMERIC(15,3) NOT NULL,
"TARIFAID"     VARCHAR(3),
"IMAPOREZ"     SMALLINT,
"POREZ"        NUMERIC(15,2) NOT NULL,
"RABAT"        NUMERIC(15,2) NOT NULL,
"MARZA"        NUMERIC(15,2) NOT NULL,
"TAKSA"        NUMERIC(15,4),
"AKCIZA"       NUMERIC(15,2),
"PROSNAB"      NUMERIC(15,4) NOT NULL,
"PRECENA"      NUMERIC(15,4) NOT NULL,
"PRENAB"       NUMERIC(15,4) NOT NULL,
"PROSPROD"     NUMERIC(15,4) NOT NULL,
"MTID"         VARCHAR(10),
"PT"           CHAR(1) NOT NULL,
"ZVEZDICA"     VARCHAR(6),
"TREN_STANJE"  NUMERIC(15,3),
"POREZ_ULAZ"   NUMERIC(15,2) NOT NULL,
"SDATUM"       DATE,
"DEVNABCENA"   NUMERIC(15,4),
"POREZ_IZ"     NUMERIC(15,2) NOT NULL,
"X4"           NUMERIC(15,3),
"Y4"           NUMERIC(15,3),
"Z4"           NUMERIC(15,3),
"CENAPOAJM"    NUMERIC(15,2),
"KGID"         INTEGER,
"SAKCIZA"      NUMERIC(15,4) NOT NULL,
CONSTRAINT "STAVKAPRIMARYKEY" PRIMARY KEY ("STAVKAID")
);

我想导出数据,但有50万行,我不知道这里会是什么样子。

所以基本上STAVKA就是DOCUMENT_ITEM在一些DOCUMENT里面该项包含该文档中该产品的ProductID (ROBAID)Price (NABAVNACENA)和其他数据。

所以现在我想遍历所有的STAVKA (DOCUMENT_ITEM),并为每个ROBAID选择最后一个Price (NABAVNACENA)

对于一个,我设法做到了这样:

SELECT
t1.STAVKAID, s.ROBAID, s.NABAVNACENA
FROM
(SELECT FIRST 1 s.STAVKAID, d.DATUM
FROM DOKUMENT d
LEFT OUTER JOIN STAVKA s ON s.VRDOK = d.VRDOK AND s.BRDOK = d.BRDOK
WHERE d.VRDOK IN (0, 11, 18, 16, 22, 1, 2, 26, 29, 30)
AND d.DATUM >= '01.01.2021'
AND d.DATUM <= '31.12.2021'
AND s.ROBAID = 39
ORDER BY DATUM DESC) AS t1 
LEFT OUTER JOIN 
STAVKA s ON t1.STAVKAID = s.STAVKAID

它返回多行,但我按DATUM DESC排序并选择第一行,这样我就为那个ROBAID选择了最后一个STAVKA

由于我有4kROBAID,我不想从我的代码中运行这个查询4k次,而是将整个表返回给它

SQL中真正有用的东西之一是,您几乎总是可以用查询替换from子句中的表名:

SELECT
s.NABAVNACENA, x.ROBAID, x.DATUM
from DOKUMENT d
LEFT OUTER JOIN STAVKA s ON s.VRDOK = d.VRDOK AND s.BRDOK = d.BRDOK
inner join
(
select s.ROBAID, max(d.DATUM) DATUM
from DOKUMENT d
LEFT OUTER JOIN STAVKA s ON s.VRDOK = d.VRDOK AND s.BRDOK = d.BRDOK
WHERE
d.VRDOK IN (0, 11, 18, 16, 22, 1, 2, 26, 29, 30)
AND d.DATUM >= '01.01.2021'
AND d.DATUM <= '31.12.2021'
AND s.ROBAID IN (39, 34)
GROUP BY s.ROBAID
) x on s.Robaid = x.robaid and d.datum = x.datum

额外的内部联接是引入所需但没有NABAVNACENA的两行的查询,并使用它将原始查询限制为这两行。

您可以直接将表连接到自身上吗?我最好使用合成ID(总是递增主键,比如一些数据库中的AutoInc字段,FB2中的Generator+Trigger(,但好吧,让我们试试日期。只是注意不要在一组中有两行或多行日期完全相同。

FB 2.1中引入的CTE将起到帮助作用:https://firebirdsql.org/refdocs/langrefupd21-select.html#langrefupd21-选择cte

WITH DOKSTAV AS (
SELECT 
s.NABAVNACENA, s.ROBAID, d.DATUM
FROM 
DOKUMENT d, STAVKA s 
WHERE s.VRDOK = d.VRDOK 
AND s.BRDOK = d.BRDOK
)
SELECT
s1.NABAVNACENA, s1.ROBAID, s1.DATUM
FROM 
DOKSTAV s1 
LEFT OUTER JOIN 
DOKSTAV s2
ON (s1.NABAVNACENA = s2.NABAVNACENA)
AND (s1.ROBAID = s2.ROBAID)
AND (s1.DATUM < s2.DATUM)
WHERE s2.DATUM IS NULL 

最新更新