简体   繁体   English

Oracle SQL:表联接

[英]Oracle SQL : table Joining

For Oracle Database, suppose I have two tables here (Similar structure, but much larger amount of data) Definition below: 对于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);

Now I want to generate a report with those columns (Get the first two payment amount and date for each customer order by paydate) : 现在,我想用这些列生成报告(按paydate获取每个客户订单的前两个付款金额和日期):

Cust_no | Cust_no | pay_amount1 | pay_amount1 | pay_date1 |pay_amount2 | pay_date1 | pay_amount2 | pay_date2 pay_date2

Sample report I want 我想要样本报告

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

Can anybody make a correct and efficient Query ? 任何人都可以进行正确有效的查询吗? Thanks ahead. 谢谢你

First you need to get your creation script right. 首先,您需要正确创建脚本。 The ; ; terminates a statement not a line inside a statement. 终止一条语句而不是一条语句。 Secondly the varchar2 data types needs a length specification: name VARCHAR2(20) instead of name VARCHAR2 . 其次, varchar2数据类型需要一个长度规范: name VARCHAR2(20)而不是name VARCHAR2 Also character literals need to be enclosed in single quotes. 字符文字也需要用单引号引起来。 '90001' is a character literal, 90001 is a number. '90001'是字符文字, 90001是数字。 Those are two different things. 那是两件事。

So this results in the following script: 因此,这将导致以下脚本:

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');

Note that it's bad coding practice to not specify the columns in an INSERT statement. 请注意,在INSERT语句中不指定列是不好的编码习惯。 It should be insert into customer (cust_no, name, zip) values(1,'Tom','90001'); 应该将其insert into customer (cust_no, name, zip) values(1,'Tom','90001'); instead of insert into customer values(1,'Tom','90001'); 而不是insert into customer values(1,'Tom','90001');


Now for your query, the following should do you wnat you need: 现在,对于您的查询,您需要满足以下条件:

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;

Note that I used an outer join to ensure that every customer is returned even if there is no or only a single payment for it. 请注意,我使用外部联接来确保即使没有付款或只有一笔付款也能返回每个客户。

Here is an SQLFiddle with all corrections and the query: http://sqlfiddle.com/#!4/74349/3 这是一个包含所有更正和查询的SQLFiddle: http ://sqlfiddle.com/#!4/74349/3

SELECT * FROM (
    SELECT 
        c.cust_no,
        p.amount as payment,
        p.date_entered as paydate,
        ROW_NUMBER() OVER (PARTITION BY cust_no ORDER BY p.record_no ASC) AS rn
    FROM customer c
        JOIN payments p ON p.cust_no = c.cust_no
    ) t 
WHERE 
    rn <= 2
ORDER BY cust_no, rn;

Will show the 2 records per client you need, in 2 separate lines. 将在2个单独的行中显示您需要的每个客户的2条记录。 If you prefer having it in the same line, then use this query: 如果您希望将其放在同一行中,请使用以下查询:

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;

The analytic function ROW_NUMBER can help you give a number to each payment : 分析功能ROW_NUMBER可以帮助您为每次付款指定一个数字:

select cust_no, amount, date_entered,
   row_number() over(partition by cust_no order by date_entered ) rn
from payments ;

Using this I think we can get what you're looking for, something like : 我想使用它,我们可以得到您想要的东西,例如:

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 ;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM