使用Oracle,我希望进行以下查询,但我想知道是否有更“智能”的方法。
ORDER BY vote ASC, (id * -1) ASC
以下是我的示例数据的样子
Select * from Sales Sales1
left join Sales Sales2 on Sales2.val = Sales1.val
left join Sales Sales3 on Sales3.val = Sales2.val
left join Sales Sales4 on Sales4.val = Sales3.val
left join Sales Sales5 on Sales5.val = Sales4.val
...
结果集看起来像这样:
customer number | acct | start balance | open date | prev account
a 1 100 01-01-15 b-1
b 1 80 03-04-14
c 2 200 04-11-14 c-1
c 1 150 06-12-15
d 1 600 08-16-15
e 3 400 12-19-15 e-2
e 2 150 10-21-14 e-1
e 1 100 01-18-13
正如您所看到的,我需要根据结果继续加入另一个销售记录,我需要继续这样做,直到我返回一个空的结果集。我当前的场景是运行查询并查看sales5,sales6,sales7等中是否有值。
答案 0 :(得分:2)
每当你必须自己加入未知次数时,你应该考虑CONNECT BY
。您的特殊需求并非如此简单,但CONNECT BY
仍然是解决方案的关键要素。
在下面的SQL中,mockup_data
子因子只是为了给我一些数据。你使用的是实际的桌子。
您的想法是搜索数据" root" - 不是任何其他记录prev_account
的记录。然后,您从那些和CONNECT BY
开始,以获得他们以前的所有帐户,尽可能多。然后你PIVOT
将它们全部放入列中。
有一件事 - Oracle SQL语句不能具有任意(数据驱动)列数。解析SQL时必须知道该数字。因此,在PIVOT
子句中,您需要指定"级别的最大数量"您将支持,以便Oracle知道结果集可以有多少列。
这是SQL。
WITH
mockup_data as (
SELECT
'a' customer_Number, 1 acct, 100 start_balance, to_date('01-01-15','MM-DD-YY') open_date, 'b-1' prev_account from dual union all
SELECT 'b' ,1, 80, to_date('03-04-14','MM-DD-YY'), null from dual union all
SELECT 'c' ,2, 200, to_date('04-11-14','MM-DD-YY'), 'c-1' from dual union all
SELECT 'c' ,1, 150, to_date('06-12-15','MM-DD-YY'), null from dual union all
SELECT 'd' ,1, 600, to_date('08-16-15','MM-DD-YY'), null from dual union all
SELECT 'e' ,3, 400, to_date('12-19-15','MM-DD-YY'), 'e-2' from dual union all
SELECT 'e' ,2, 150, to_date('10-21-14','MM-DD-YY'), 'e-1' from dual union all
SELECT 'e' ,1, 100, to_date('01-18-13','MM-DD-YY'), null from dual ),
data_with_roots AS
(SELECT d.*,
CASE
WHEN (SELECT COUNT (*)
FROM mockup_data d2
WHERE d2.prev_account = d.customer_number || '-' || d.acct) = 0 THEN
'Y'
ELSE
'N'
END
is_root
FROM mockup_data d),
hierarchy AS
(SELECT CONNECT_BY_ROOT (customer_number) customer_number,
CONNECT_BY_ROOT (acct) acct,
CONNECT_BY_ROOT (start_balance) start_balance,
CONNECT_BY_ROOT (open_date) open_date,
start_balance prev_start_balance,
open_date prev_open_date,
LEVEL - 1 lvl
FROM data_with_roots d
CONNECT BY customer_number || '-' || acct = PRIOR prev_account
START WITH is_root = 'Y'),
previous_only AS
(SELECT *
FROM hierarchy
WHERE lvl >= 1)
SELECT *
FROM previous_only PIVOT (MAX (prev_start_balance) AS prev_start, MAX (prev_open_date) AS prev_open
FOR lvl
IN (1 AS "01", 2 AS "02", 3 AS "03", 4 AS "04", 5 AS "05" -- etc... as many levels as you need to support
));