4.5 维表过滤

4.5.1 过滤后复用索引

SQL

SELECT Suppliers.Region,sum(Amount) Amount
FROM Orders
LEFT JOIN Products ON Orders.ProductID= Products.ProductID
LEFT JOIN Suppliers ON Products.SupplierID=Suppliers.SupplierID
WHERE OrderDate>='2021-01-01' and OrderDate<='2021-12-31' and Products.CategoryID not in (1,2,3)
GROUP BY Suppliers.Region

SPL

A
1 >st=date(“2021-01-01”), et=date(“2021-12-31”), start= days@o(st), end=days@o(et)
2 =Products.select@i([1,2,3].pos@b(CategoryID)==null)
3 =file(“Orders_Time.ctx”).open().cursor@mx(ProductID, Amount; OrderDate>=start && OrderDate<=end, ProductID:A2)
4 =A3.groups(ProductID.SupplierID.Region;sum(Amount):Amount)

A2 对维表过滤时使用 @i 选项将复用索引
A3 把和维表的关联放到产生游标的语句中,关联不上的记录不生成,减少生成记录的时间

索引复用并不会总是更快,因为要把过滤掉的记录从索引表删除,如果过滤掉的记录数很多(剩下的较少),这个动作也不会很快。而剩下记录较少时,重建索引很可能更快。具体采用哪种方式,要根据实际情况决定。

4.5.2 过滤后重建索引

SQL

SELECT Suppliers.Region,sum(Amount) Amount
FROM Orders
LEFT JOIN Products ON Orders.ProductID= Products.ProductID
LEFT JOIN Suppliers ON Products.SupplierID=Suppliers.SupplierID
WHERE OrderDate>='2021-01-01' and OrderDate<='2021-12-31' and Products.CategoryID in (1,2,3)
GROUP BY Suppliers.Region

SPL

A
1 >st=date(“2021-01-01”), et=date(“2021-12-31”), start=days@o(st), end=days@o(et)
2 =Products.select([1,2,3].pos@b(CategoryID)!=null).derive@o().keys@i(ProductID)
3 =file(“Orders_Time.ctx”).open().cursor@mx(ProductID,Amount;OrderDate>=start && OrderDate<=end,ProductID:A2)
4 =A3.groups(ProductID.SupplierID.Region;sum(Amount):Amount)

A2 维表过滤后返回序列,用 derive@o() 变回序表,再重建索引

本例过滤掉的记录数很多(剩下的较少),重建索引很快。

4.5.3 多层维表的过滤

SQL

SELECT Suppliers.Region,sum(Amount) Amount
FROM Orders
INNER JOIN Products ON Orders.ProductID= Products.ProductID
INNER JOIN Suppliers ON Products.SupplierID=Suppliers.SupplierID
WHERE OrderDate>='2021-01-01' and OrderDate<='2021-12-31' 
    and Suppliers.SupplierID in (1,2,3) and Products.CategoryID in (1,2,3,4,5)
GROUP BY Suppliers.Region

SPL

多层维表的过滤,需要先把维表各自过滤后再建立关联关系,关联时只保留能关联上的记录。

A
1 =Suppliers.select@i([1,2,3].pos@b(SupplierID)!=null)
2 =Products.select@i([1,2,3,4,5].pos@b(CategoryID)!=null)
3 =A2.switch@i(SupplierID, A1:SupplierID)

A1 过滤供应商维表
A2 过滤产品维表
A3 将过滤后的 Products 和 Suppliers 建立关联,@i 选项表示关联不上的记录删除

统计时直接使用:

A
/ 接上面代码
4 >st=date(“2021-01-01”), et=date(“2021-12-31”), start=days@o(st), end=days@o(et)
5 =file(“Orders_Time.ctx”).open().cursor@mx(ProductID, Amount; OrderDate>=start && OrderDate<=end, ProductID:A3)
6 =A5.groups(ProductID.SupplierID.Region; sum(Amount):Amount)

A5 和过滤后的维表关联,关联不上的记录不再生成

4.5.4 反向过滤

SQL

SELECT sum(Amount)
FROM Orders
WHERE OrderDate>='2021-01-01' and OrderDate<='2021-12-31' and EmployeeID not in (
    SELECT EmployeeID 
    FROM Employees 
    WHERE Title='Sales Representative') 

SPL

A
1 >st=date(“2021-01-01”), et=date(“2021-12-31”), start=days@o(st), end=days@o(et)
2 >Employees=file(“Employees.btx”).import@b().select(Title==“Sales Representative”).derive().keys@i(EmployeeID)
3 =file(“Orders_Time.ctx”).open().cursor@mx(Amount;OrderDate>=start && OrderDate<=end,EmployeeID:Employees:null)
4 =A3.groups(;sum(Amount))

A3 在组表游标中和维表关联,加上:null 表示仅选出关联不上的记录

如果不是组表,使用 switch 关联的话,可以用 @d 选项,即可选出关联不上的记录