我试图只从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