简体   繁体   English

使用多个条件进行自联接

[英]Self-join using multiple conditions

Identify the purchase details of books, where the book is purchased on the same date, exactly on the date Anne has purchased the book.确定书籍的购买详细信息,这本书是在同一日期购买的,恰好是安妮购买这本书的日期。 Write a SQL query to display customer's name and title of the book for the identified purchase details.编写 SQL 查询以显示客户姓名和书名,以获取已识别的购买详细信息。 Do NOT display details of Anne in the query result.不要在查询结果中显示 Anne 的详细信息。

There are these 3 tables for these requirements:这些要求有以下 3 个表:

Book :

('B101', 'Science Revolution', 'Journal')
('B102', 'Brain Teasers', 'Aptitude')
('B103', 'India Today', 'Magazine')
('B104', 'Tech World', 'Journal')
('B105', 'Bizz world', 'Magazine') 

Customer顾客

('C101', 'Jack')
('C102', 'Anne')
('C103', 'Jane')
('C104', 'Maria') 

Purchase :购买

('P201', 'C101', 'B102', '12-Dec-19')
('P202', 'C102', 'B103', '25-Nov-19')
('P203', 'C103', 'B104', '12-Dec-19')
('P204', 'C104', 'B105', '25-Nov-19') 
('P205', 'C101', 'B101', '11-Dec-19')
('P206', 'C101', 'B106', '12-Dec-19') 

I used the following logic for the above requirement我对上述要求使用了以下逻辑

select 
    b.bookname, c.custname 
from 
    customer c 
join 
    purchase p on c.custid > p.custid 
join 
    purchase p1 on p.custid > p1.custid 
                and p.purchasedate = p1.purchasedate 
join 
    book b on b.bookid = p1.bookid 
group by 
    b.bookname, c.custname;

Can anyone provide correct solution?谁能提供正确的解决方案? Only 'Maria' 'Bizz world' has to appear in the result.只有“Maria”“Bizz world”必须出现在结果中。

Step 1步骤1

 -- -- what did Anne purchase? -- select c.custname, p.* from purchase as p join customer as c on c.custid = p.custid where c.custname = 'Anne';
 custname |客户名 | purchaseid |购买ID | custid |监护人 | bookid |书号 | purchasedate:------- |:--------- |:----- |:----- |:----------- Anne |购买:------- |:--------- |:----- |:----- |:----------- 安妮 | P202 | P202 | C102 | C102 | B103 | B103 | 25-Nov-19 19 年 11 月 25 日

Step 2第2步

-- -- Any purchases on the same dates as Anna by other people? -- select p2.* from purchase as p1 join customer as c1 on c1.custid = p1.custid join purchase as p2 on p2.purchasedate = p1.purchasedate and p2.custid.= p1.custid where c1;custname = 'Anne';
 purchaseid |购买ID | custid |监护人 | bookid |书号 | purchasedate:--------- |:----- |:----- |:----------- P204 |购买:--------- |:----- |:----- |:----------- P204 | C104 | C104 | B105 | B105 | 25-Nov-19 19 年 11 月 25 日

Step 3第 3 步

-- -- Now get the names from those id's -- select c2.custname, b2.bookname from purchase as p1 join customer as c1 on c1.custid = p1.custid join purchase as p2 on p2.purchasedate = p1.purchasedate and p2.custid.= p1.custid join customer as c2 on c2.custid = p2.custid join book as b2 on b2.bookid = p2.bookid where c1.custname = 'Anne'
 custname |客户名 | bookname:------- |:--------- Maria |书名:------- |:--------- 玛丽亚 | Bizz world商业世界

Demo on db<>fiddle here关于db<>fiddle 的演示在这里

In similar construct as LukStorms provided, first, lets start with how to get the date that Anne purchased the book.在与 LukStorms 提供的类似结构中,首先,让我们从如何获取 Anne 购买这本书的日期开始。 That is the first and foremost requirement for your query.这是您查询的首要要求。 I like to show indentation of the queries how table A gets to B gets to C, etc.我喜欢显示查询的缩进,表 A 到 B 到 C 等。

You already had many joins, I am just showing the first part.你已经有很多连接了,我只展示第一部分。 Get the who, and the date of their purchase.获取购买者和购买日期。 In this case, I am also getting the customer's ID so I know which ID to EXCLUDE from the final answer.在这种情况下,我还获得了客户的 ID,因此我知道要从最终答案中排除哪个 ID。 Dont rely on knowing their customer ID and knowing you want purchases with the ID greater than the person.不要依赖于知道他们的客户 ID 并知道您想要 ID 大于个人的购买。 What if you have 5000 people, and Anne happened to be person 2789. Doing greater than would fail on any that also purchsed same date but fail on customer ID.如果你有 5000 个人,而 Anne 恰好是第 2789 个人会怎样。在任何购买相同日期但在客户 ID 上失败的情况下,做得比其他人都失败。

select
        p.custid,
        p.purchaseDate
    from
        customer c
            join purchase p
                on c.custid = p.custid
    where
        c.custname = 'Anne'

So from here, this can be the FIRST alias of the final select because the basis was to have the DATE of the purchase, but also now we KNOW the WHO we DONT want in the result.所以从这里开始,这可能是最终 select 的第一个别名,因为基础是购买日期,但现在我们知道结果中我们不想要的人。

select
        AnnePurchase.purchaseDate,
        c2.custname,
        b.bookName
    from
        (select
                p.custid,
                p.purchaseDate
            from
                customer c
                    join purchase p
                        on c.custid = p.custid
            where
                c.custname = 'Anne' ) AnnePurchase
            JOIN purchase p2
                -- first part, join to purchase on same date as Ann purchased her book
                on AnnePurchase.purchaseDate = p2.purchaseDate
                -- but now, get anyone who's customer ID is NOT the same as Anne.
                AND NOT AnnePurchase.custID = p2.custID
                -- now from the 2nd purchase table we can join to the customer and book 
                -- table to get whatever other parts you want
                JOIN customer c2
                    on p2.custid = c2.custid
                JOIN book b
                    on p2.bookid = b.bookid

Notice the in-line comments via -- that show WHY I am doing the join.请注意通过 -- 显示我为什么要加入的在线评论。 The AnnePurchase is the primary basis. AnnePurchase 是主要依据。 The join to Purchase (alias p2) is to get based on the same date and NOT the same customer ID as Anne.加入购买(别名 p2)是基于相同的日期而不是与 Anne 相同的客户 ID。

From that, its a simple join from the P2 alias back to the customer and book tables.从那里,它是从 P2 别名返回到客户和预订表的简单连接。 I personally have the indentation of the joins for customer c2 and book b indented under the purchase p2 because THAT is the basis of their relationship.我个人在购买 p2 下缩进了customer c2book b的连接缩进,因为这是他们关系的基础。

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

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