Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
oraclesql:表连接_Sql_Oracle - Fatal编程技术网

oraclesql:表连接

oraclesql:表连接,sql,oracle,Sql,Oracle,对于Oracle数据库,假设我在这里有两个表,结构相似,但下面的数据定义量要大得多: create table payments( record_no INTEGER; cust_no INTEGER; amount NUMBER; date_entered DATE; ); insert into payments values(1,3,34.5,sysdate-1); insert into payments values(2,2,34.5,sysdate-2

对于Oracle数据库,假设我在这里有两个表,结构相似,但下面的数据定义量要大得多:

create table payments(
    record_no INTEGER;
    cust_no INTEGER;
    amount NUMBER;
    date_entered DATE;
);
insert into payments values(1,3,34.5,sysdate-1);
insert into payments values(2,2,34.5,sysdate-2);
insert into payments values(3,3,34.5,sysdate-18/1440);
insert into payments values(4,1,34.5,sysdate-1);
insert into payments values(5,2,34.5,sysdate-2/24);
insert into payments values(6,3,34.5,sysdate-56/1440);
insert into payments values(7,4,34.5,sysdate-2);
insert into payments values(8,2,34.5,sysdate-1);

create table customer(
    cust_no INTEGER;
    name VARCHAR2;
    zip VARCHAR2;
);
insert into customer values(1,'Tom',90001);
insert into customer values(2,'Bob',90001);
insert into customer values(3,'Jack',90001);
insert into customer values(4,'Jay',90001);
现在,我想生成一个包含这些列的报告,按paydate获取每个客户订单的前两个付款金额和日期:

客户编号|付款金额1 |付款日期1 |付款金额2 |付款日期2

我想要一份样本报告

CUST_NO PAYMENT1    PAYDATE1     PAYMENT2      PAYDATE2
1   34.5    October, 09 2013     0             null
2   34.5    October, 08 2013     34.5      October, 09 2013
3   34.5    October, 09 2013     34.5      October, 10 2013
4   34.5    October, 08 2013     0             null

任何人都能做出正确有效的查询吗?谢谢。首先,您需要正确地编写创建脚本。这个终止语句,而不是语句内的一行。其次,varchar2数据类型需要一个长度规范:名称VARCHAR220而不是名称varchar2。此外,字符文字还需要用单引号括起来。”90001'是字符文字,90001是数字。这是两件不同的事情

因此,这将产生以下脚本:

create table payments(
    record_no INTEGER,
    cust_no INTEGER,
    amount NUMBER,
    date_entered DATE
);

insert into payments values(1,3,34.5,sysdate-1);
insert into payments values(2,2,34.5,sysdate-2);
insert into payments values(3,3,34.5,sysdate-18/1440);
insert into payments values(4,1,34.5,sysdate-1);
insert into payments values(5,2,34.5,sysdate-2/24);
insert into payments values(6,3,34.5,sysdate-56/1440);
insert into payments values(7,4,34.5,sysdate-2);
insert into payments values(8,2,34.5,sysdate-1);

create table customer(
    cust_no INTEGER,
    name VARCHAR2(20),
    zip VARCHAR2(20)
);

insert into customer values(1,'Tom','90001');
insert into customer values(2,'Bob','90001');
insert into customer values(3,'Jack','90001');
insert into customer values(4,'Jay','90001');
请注意,在INSERT语句中不指定列是不好的编码实践。应将其插入客户编号、姓名、邮政编码1、“Tom”和“90001”中;而不是在客户价值1中插入“Tom”和“90001”

现在,对于您的查询,您需要执行以下操作:

with numbered_payments as (
  select cust_no, 
         amount, 
         date_entered, 
         row_number() over (partition by cust_no order by date_entered) as rn
  from payments
) 
select c.cust_no,
       c.name, 
       p1.amount as pay_amount1,
       p1.date_entered as pay_date1,
       p2.amount as pay_amount2, 
       p2.date_entered as pay_date2
from customer c
  left join numbered_payments p1 
         on p1.cust_no = c.cust_no 
        and p1.rn = 1
  left join numbered_payments p2 
         on p2.cust_no = c.cust_no 
        and p2.rn = 2;
注意,我使用了一个外部连接来确保每个客户都被返回,即使没有或只有一次付款


下面是一个包含所有更正和查询的SQLFIDLE:

首先,您需要正确地获取创建脚本。这个终止语句,而不是语句内的一行。其次,varchar2数据类型需要一个长度规范:名称VARCHAR220而不是名称varchar2。此外,字符文字还需要用单引号括起来。”90001'是字符文字,90001是数字。这是两件不同的事情

因此,这将产生以下脚本:

create table payments(
    record_no INTEGER,
    cust_no INTEGER,
    amount NUMBER,
    date_entered DATE
);

insert into payments values(1,3,34.5,sysdate-1);
insert into payments values(2,2,34.5,sysdate-2);
insert into payments values(3,3,34.5,sysdate-18/1440);
insert into payments values(4,1,34.5,sysdate-1);
insert into payments values(5,2,34.5,sysdate-2/24);
insert into payments values(6,3,34.5,sysdate-56/1440);
insert into payments values(7,4,34.5,sysdate-2);
insert into payments values(8,2,34.5,sysdate-1);

create table customer(
    cust_no INTEGER,
    name VARCHAR2(20),
    zip VARCHAR2(20)
);

insert into customer values(1,'Tom','90001');
insert into customer values(2,'Bob','90001');
insert into customer values(3,'Jack','90001');
insert into customer values(4,'Jay','90001');
请注意,在INSERT语句中不指定列是不好的编码实践。应将其插入客户编号、姓名、邮政编码1、“Tom”和“90001”中;而不是在客户价值1中插入“Tom”和“90001”

现在,对于您的查询,您需要执行以下操作:

with numbered_payments as (
  select cust_no, 
         amount, 
         date_entered, 
         row_number() over (partition by cust_no order by date_entered) as rn
  from payments
) 
select c.cust_no,
       c.name, 
       p1.amount as pay_amount1,
       p1.date_entered as pay_date1,
       p2.amount as pay_amount2, 
       p2.date_entered as pay_date2
from customer c
  left join numbered_payments p1 
         on p1.cust_no = c.cust_no 
        and p1.rn = 1
  left join numbered_payments p2 
         on p2.cust_no = c.cust_no 
        and p2.rn = 2;
注意,我使用了一个外部连接来确保每个客户都被返回,即使没有或只有一次付款

这是一个包含所有更正和查询的SQLFIDLE:

分析函数ROW\u NUMBER可以帮助您为每笔付款提供一个数字:

select cust_no, amount, date_entered,
   row_number() over(partition by cust_no order by date_entered ) rn
from payments ;
我想我们可以用这个来得到你想要的东西,比如:

With ordered_payments as (
    select cust_no, amount, date_entered,
       row_number() over(partition by cust_no order by date_entered ) rn
       from payments)
select customer.cust_no, p1.amount, p1.date_entered, p2.amount, p2.date_entered
from customer left join ordered_payments p1 
                     on customer.cust_no = p1.cust_no and p1.rn = 1
              left join ordered_payments p2 
                     on customer.cust_no = p2.cust_no and p2.rn = 2 ;
分析函数ROW_NUMBER可帮助您为每笔付款提供一个数字:

select cust_no, amount, date_entered,
   row_number() over(partition by cust_no order by date_entered ) rn
from payments ;
我想我们可以用这个来得到你想要的东西,比如:

With ordered_payments as (
    select cust_no, amount, date_entered,
       row_number() over(partition by cust_no order by date_entered ) rn
       from payments)
select customer.cust_no, p1.amount, p1.date_entered, p2.amount, p2.date_entered
from customer left join ordered_payments p1 
                     on customer.cust_no = p1.cust_no and p1.rn = 1
              left join ordered_payments p2 
                     on customer.cust_no = p2.cust_no and p2.rn = 2 ;
将在两行中显示每个客户端所需的2条记录。如果希望将其放在同一行中,请使用以下查询:

SELECT
    cust_no,
    payment1,
    paydate1,
    CASE WHEN nextcli <> cust_no THEN 0 ELSE payment2 END AS payment2,
    CASE WHEN nextcli <> cust_no THEN SYSDATE ELSE paydate2 END AS paydate2
FROM (
    SELECT 
        c.cust_no,
        p.amount as payment1,
        p.date_entered as paydate1,
        ROW_NUMBER() OVER (PARTITION BY c.cust_no ORDER BY p.record_no ASC) AS rn,
        LEAD(c.cust_no, 1, -1) OVER (ORDER BY c.cust_no ASC) as nextcli,
        LEAD(p.amount, 1, 0) OVER (ORDER BY c.cust_no ASC) as payment2,
        LEAD(p.date_entered, 1, NULL) OVER (ORDER BY c.cust_no ASC) as paydate2
    FROM customer c
        JOIN payments p ON p.cust_no = c.cust_no
    ) t 
WHERE 
    rn <= 1
ORDER BY cust_no, rn;
将在两行中显示每个客户端所需的2条记录。如果希望将其放在同一行中,请使用以下查询:

SELECT
    cust_no,
    payment1,
    paydate1,
    CASE WHEN nextcli <> cust_no THEN 0 ELSE payment2 END AS payment2,
    CASE WHEN nextcli <> cust_no THEN SYSDATE ELSE paydate2 END AS paydate2
FROM (
    SELECT 
        c.cust_no,
        p.amount as payment1,
        p.date_entered as paydate1,
        ROW_NUMBER() OVER (PARTITION BY c.cust_no ORDER BY p.record_no ASC) AS rn,
        LEAD(c.cust_no, 1, -1) OVER (ORDER BY c.cust_no ASC) as nextcli,
        LEAD(p.amount, 1, 0) OVER (ORDER BY c.cust_no ASC) as payment2,
        LEAD(p.date_entered, 1, NULL) OVER (ORDER BY c.cust_no ASC) as paydate2
    FROM customer c
        JOIN payments p ON p.cust_no = c.cust_no
    ) t 
WHERE 
    rn <= 1
ORDER BY cust_no, rn;

不仅速度慢,查询中使用的rownum谓词还会给您一个随机行。查阅文档以了解使用rownum的正确方法-谷歌搜索Oracle rownum可能会抛出大量示例。此查询在Oracle上的leat是错误的,最后两个子查询给出错误c.cust_no-无效标识符-查看此演示:@kordirko我注意到并修改了我的问题,感谢您指出,那么你的解决方案是什么呢?你不需要;和/for DDL语句。您只需要/for PL/SQL块。事实上,CREATETABLE语句将执行两次,您可能想知道为什么总是出现“TABLE ALEXISTS”错误。请参见此处了解详细信息:它仍然是错误的->,这次给出了一个语法错误:ORA-00907:缺少右括号。很难优化不编译的q查询,请更正它。它不仅速度慢,而且查询中使用的rownum谓词会给您一个随机行。查阅文档以了解使用rownum的正确方法-谷歌搜索Oracle rownum可能会抛出大量示例。此查询在Oracle上的leat是错误的,最后两个子查询给出错误c.cust_no-无效标识符-查看此演示:@kordirko我注意到并修改了我的问题,感谢您指出,那么你的解决方案是什么呢?你不需要;和/for DDL语句。您只需要/for PL/SQL块。事实上,CREATETABLE语句将执行两次,您可能想知道为什么总是出现“TABLE ALEXISTS”错误。请参见此处了解详细信息:它仍然是错误的->,这次给出了一个语法错误:ORA-00907:缺少右括号。很难优化不编译的q查询,请更正。