我希望我的Firebird SQL在满足条件时遍历部分代码。
最初,我什至不认为这是可能的。但是,我已经读了一些书,现在相信我可以使用WHILE循环。
我了解到FOR循环不是我想要的,因为它不仅适用于整个代码,而且适用于整个代码。
我正在Excel中使用它,并且可以使用一些VBA代码来执行我想要的操作,但是如果我可以通过Firebird SQL进行所有操作,那将更好,然后再将其应用于其他地方。
SELECT
'1' as "Qty",
'of ' || ALP3.PROPERTYVALUE AS "Total Qty"
FROM ASSEMBLYLINES
LEFT JOIN ASSEMBLYLINEPROPS ALP1 ON ALP1.HEADERSYSUNIQUEID = ASSEMBLYLINES.SYSUNIQUEID AND ALP1.PROPERTYNAME = 'Process2'
LEFT JOIN ASSEMBLYLINEPROPS ALP2 ON ALP2.HEADERSYSUNIQUEID = ASSEMBLYLINES.SYSUNIQUEID AND ALP2.PROPERTYNAME = 'Process3'
LEFT JOIN ASSEMBLYLINEPROPS ALP3 ON ALP3.HEADERSYSUNIQUEID = ASSEMBLYLINES.SYSUNIQUEID AND ALP3.PROPERTYNAME = 'Job Quantity'
LEFT JOIN ASSEMBLYLINEPROPS ALP4 ON ALP4.HEADERSYSUNIQUEID = ASSEMBLYLINES.SYSUNIQUEID AND ALP4.PROPERTYNAME = 'Drawing No'
WHERE ASSEMBLYLINES.ORDERNUMBER='16708R01'
AND ASSEMBLYLINES.LINECODE='FABPART'
AND ASSEMBLYLINES.SYSUSERCREATED <> 'EXTERNAL USER'
ORDER BY ALP4.PROPERTYVALUE
使用以上代码的结果是:
Qty Total Qty 1 4
但是,我想要的是:
使用以上代码的结果是:
Qty Total Qty 1 4 2 4 3 4 4 4
我了解While循环将类似于:
While Qty <= ALP3.PROPERTYVALUE Do
<<output>>
Loop
答案 0 :(得分:1)
Qty Total Qty
1 4
2 4
3 4
4 4
I understand the While loop would be something like:
While Qty <= ALP3.PROPERTYVALUE Do
<<output>>
Loop
因此,“数量”列实际上不是一些实际数据的数量(例如,货船中集装箱的数量),而是某些输出报告/网格中的行号。 然后,您想要将输出“行集”(矩阵,表格,网格)限制为前N个行。
好吧,就是这样,只要求第一行。
Select FIRST(4) column1, column2, column3
From table 1
Where condition1 and condition2 or condition3
请参见文档中的“第一”条款:https://www.firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-dml-select.html
另请参见Wikipedia中的“限制结果行”专栏文章:https://en.wikipedia.org/wiki/Select_%28SQL%29#Limiting_result_rows
从Firebird版本3开始,您还可以使用“窗口函数”,但是对于“只给我前N行给我”这样简单的任务,它们有些过高。
现在,还有另一种方法可以嵌入完全自愿的条件,但这是来自“丑陋的hacks”工具集的,并且在运行多个同时连接的不同客户端程序的典型情况下,该方法不起作用。您可以在WHILE子句中使用“生成器”:
Select .....
Where (GEN_ID(cancel_generator_name, 0) = 0) AND ( ...you normal conditions...)
您在查询之前将生成器值设置为0,并且客户端在读取数据时会评估您选择的某些条件,并且在需要时-从另一个SQL命令库对象中发出生成器更改命令,该命令将立即跳过其余查询。但是,尽管有时这是一种有用的技术,但仅在非常特殊的罕见情况下才可以。
由于Mark的猜测似乎比我更好,所以为将来的猜测提供了一些轮廓。
SP是SQL存储过程的标准缩写。 Firebird的Execute Block
本质上是一个匿名的非永久性SP。
因此,我们从一个持久的,命名为SP开始。
create or alter procedure SEQ (
FROM_1_TO integer not null)
returns (
COUNTER integer)
as
begin
counter = 1;
while ( counter <= from_1_to ) do begin
suspend;
counter = counter + 1;
end
end
Select 1, s.counter from rdb$database, seq(5) s
CONSTANT COUNTER
1 1
1 2
1 3
1 4
1 5
下一个问题是如何
答案是-LEFT JOIN
,如常见问题解答中所示:http://www.firebirdfaq.org/faq143/
CREATE TABLE T2 (
ID INTEGER NOT NULL PRIMARY KEY,
TITLE VARCHAR(10) NOT NULL,
QTY INTEGER NOT NULL
);
INSERT INTO T2 (ID, TITLE, QTY) VALUES (1, 'aaaa', 2);
INSERT INTO T2 (ID, TITLE, QTY) VALUES (2, 'bbbb', 5);
INSERT INTO T2 (ID, TITLE, QTY) VALUES (3, 'ccccc', 4);
Select * from t2 t
left join seq(t.qty) s on 1=1
ID TITLE QTY COUNTER
1 aaaa 2 1
1 aaaa 2 2
2 bbbb 5 1
2 bbbb 5 2
2 bbbb 5 3
2 bbbb 5 4
2 bbbb 5 5
3 ccccc 4 1
3 ccccc 4 2
3 ccccc 4 3
3 ccccc 4 4
如果您对不同的表/字段有许多不同的查询,需要添加此行克隆,那么使用专用的计数器生成SP就很有意义。
但是,如果您只需要克隆一次这种非常奇特的行,那么也许再也不需要用SP污染全局名称空间了。
但是似乎无法从EB中进行选择:Select from execute block?
因此,您必须准确地为您的select
语句创建特定的临时EB。可以说,这可能是匿名非持久性EB的真正原因。
execute block
returns (ID INTEGER, TITLE VARCHAR(10), QTY INTEGER, COUNTER INTEGER)
as
begin
for select
id, title, qty from t2
into :id, :title, :qty
do begin
counter = 1;
while
(counter <= qty)
do begin
suspend;
counter = counter + 1;
end
end
end
但是,您的应用程序用于连接到Firebird的数据访问库应该了解,那么尽管此查询不是SELECT查询,它仍会返回“行集”。他们通常会这么做,但是谁知道呢。