0

有两个表:

CREATE TABLE STORE ( 
  ID INTEGER NOT NULL,  
  MEDICINE_ID INTEGER NOT NULL,  
  SHIPMENT_ID INTEGER NOT NULL,  
  PACKAGE_ID INTEGER NOT NULL,  
  QUANTITY INTEGER NOT NULL);  

CREATE TABLE ORDERS (  
  ID INTEGER NOT NULL,  
  CLIENT_ID INTEGER NOT NULL,
  STORE_ITEM_ID INTEGER NOT NULL,
  QUANTITY INTEGER NOT NULL,
  ORDERDATE DATE NOT NULL,
  STATE INTEGER DEFAULT 1 NOT NULL);

我在这里只写了字段,没有生成器、触发器、键等

下一个视图选择每个日期最受欢迎的药物:

CREATE VIEW ORDERS_STORE_QTY
AS
SELECT
  O1.ORDERDATE,
  S1.MEDICINE_ID,
  SUM(O1.QUANTITY) AS QTY
FROM ORDERS O1
INNER JOIN STORE S1 ON (S1.ID = O1.STORE_ITEM_ID)
WHERE O1.STATE=5 /* the closed order */
GROUP BY O1.ORDERDATE, MEDICINE_ID
ORDER BY O1.ORDERDATE, SUM(O1.QUANTITY) DESC

然后我将视图与自身进行左连接,并在条件下比较汇总数量:

SELECT T1.ORDERDATE, T1.MEDICINE_ID, T1.QTY
  FROM ORDERS_STORE_QTY T1
  LEFT OUTER JOIN ORDERS_STORE_QTY T2
  ON (
        T1.ORDERDATE = T2.ORDERDATE
        AND
        T2.QTY > T1.QTY 
     )
   GROUP BY T1.ORDERDATE, T1.MEDICINE_ID, T1.QTY
   HAVING COUNT(T2.MEDICINE_ID) < 5
   ORDER BY T1.ORDERDATE, T1.QTY DESC

如果每天的所有汇总数量都不同,我没有问题。我的任务是将“最佳”药物限制为每天五种,但有时会有重复的数量,所以 我得到的不是序列0、1、2、3、4 :
0、1、2、2、2、3、4 , 5例如。

如何更改查询(我宁愿不使用生成器也不使用非规范化)以真正限制行数?

所有代码都接近于纯 SQL(我希望如此)并为 Firebird 2.5 编写。

4

2 回答 2

1

我相信您可以将 self join 中的 on 子句更改为:

ON T1.ORDERDATE = T2.ORDERDATE AND 
   (T2.QTY > T1.QTY or
    (T2.QTY = T1.QTY and t2.Medicine_ID < t1.Medicine_ID)
   )

这样做是通过强制执行严格的排序来消除联系——首先是数量,然后是药物 ID。

哦,如果您使用支持窗口函数(row_number())的数据库,这会容易得多;)

于 2012-06-20T18:18:25.093 回答
0

尝试将DISTINCT关键字添加到您的SELECT语句中以消除任何重复项。

于 2012-06-20T18:17:22.950 回答