简体   繁体   English

当一个表为空时,查询在内部连接期间不返回任何内容

[英]Query returns nothing during inner join when one table empty

I am creating a library management system.我正在创建一个图书馆管理系统。

I am trying to query a SQL database through VB.NET with an inner join function, and return data to a datagridview, what I am looking for is a return of something, I do not know the best way to proceed.我正在尝试使用内部连接 function 通过 VB.NET 查询 SQL 数据库,并将数据返回到 datagridview,我正在寻找的最好的方法是不知道的返回。

I have a table called Onloan that holds basic information about the loan, an id for the user UNID , a ISBN for the book, start and end dates along with returned date, then inner joined with the enrolment table, for the user, and catalogue table, for the books, to create a full picture of what loan is active, for what and by who, but I have a reset function on the program that allows the administrator or senior librarian reset a specific table for example the users table, but the current code will not show any results is the users table is empty, obviously it will not because of the statement that I used, meaning that the dashboard will not be correct我有一个名为Onloan的表,其中包含有关贷款的基本信息、用户UNID的 id、书籍的 ISBN、开始和结束日期以及返回日期,然后与用户和目录的注册表内部连接表,对于书籍,创建一个完整的贷款是活跃的,对于什么和谁,但是我在程序上有一个重置 function,它允许管理员或高级图书管理员重置一个特定的表,例如用户表,但是当前代码不会显示任何结果是用户表是空的,显然不是因为我使用的语句,这意味着仪表板将不正确

SELECT OnLoan.UNID, OnLoan.ISBN, Catalogue.Title
  , Enrolment.Firstname + ' ' + Enrolment.Lastname As 'Full Name'
  , Enrolment.House + Enrolment.TutorGroup as Form
  , OnLoan.StartDate, OnLoan.EndDate
FROM (Catalogue
INNER JOIN OnLoan ON Onloan.ISBN = Catalogue.ISBN)
INNER JOIN Enrolment ON Enrolment.UNID = OnLoan.UNID
WHERE OnLoan.OnLoan = 1
and OnLoan.EndDate >= CONVERT(datetime, '" & DateTime.Now.ToString("yyyy-MM-dd") & "' )

The image is for the dashboard in the onloan and overdue datagrids I want information even if the data is not completed.该图像用于 onloan 和过期数据网格中的仪表板,即使数据未完成,我也想要信息。 Just place a "Unknown user" there or something.只需在那里放置一个“未知用户”或其他东西。

仪表板的图像

I just want information and references for areas I should look at, if you are able to edit my code and let me use it, that would be great, but any information and help you can provide would be appreciated.我只想要我应该查看的区域的信息和参考,如果您能够编辑我的代码并让我使用它,那就太好了,但是您可以提供的任何信息和帮助将不胜感激。

You need to investigate OUTER JOINs.您需要调查 OUTER JOIN。 These types of JOINS will return all the results of a JOIN from a specific side regardless if there is a matching item in the other table.这些类型的 JOIN 将返回来自特定端的 JOIN 的所有结果,而不管其他表中是否存在匹配项。 I created your tables in postgres and gave it a run.我在 postgres 中创建了你的表并试了一下。

Table Creation表创建

    CREATE TABLE Catalogue (
        Title VARCHAR,
        ISBN VARCHAR,
        PRIMARY KEY (ISBN)
    );

    CREATE TABLE Enrolment (
        UNID serial PRIMARY KEY,    
        Firstname VARCHAR,
        Lastname VARCHAR,
        House VARCHAR,
        TutorGroup VARCHAR
    );

    CREATE TABLE OnLoan (
        UNID serial PRIMARY KEY,
        ISBN VARCHAR,
        OnLoan integer, 
        StartDate TIMESTAMP DEFAULT NOW(),
        EndDate TIMESTAMP DEFAULT (NOW() + interval '21 days')
    );

Seed the tables with data用数据播种表

    INSERT INTO Catalogue (Title, ISBN) VALUES ('Harry Potter and the Sorcerer''s Stone', '978-0439708180');
    INSERT INTO Catalogue (Title, ISBN) VALUES ('Harry Potter and the Chamber of Secrets', '978-0439064873');
    INSERT INTO Catalogue (Title, ISBN) VALUES ('Harry Potter And The Prisoner Of Azkaban', '978-0439136365');
    INSERT INTO Catalogue (Title, ISBN) VALUES ('Harry Potter And The Goblet Of Fire', '978-0439139601');

    INSERT INTO Enrolment (Firstname, Lastname, House, TutorGroup) VALUES ('Harry','Potter','Gryffindor','Granger Study Group');
    INSERT INTO Enrolment (Firstname, Lastname, House, TutorGroup) VALUES ('Hermione','Granger','Gryffindor','Granger Study Group');
    INSERT INTO Enrolment (Firstname, Lastname, House, TutorGroup) VALUES ('Ronald','Weasley','Gryffindor','Granger Study Group');
    INSERT INTO Enrolment (Firstname, Lastname, House, TutorGroup) VALUES ('Draco','Malfoy','Slytherin','Snape''s Dungeon Group');


    INSERT INTO OnLoan (UNID, ISBN, OnLoan) 
    VALUES (
        (SELECT e.UNID FROM Enrolment e WHERE e.Lastname='Malfoy'),
        (SELECT c.ISBN FROM Catalogue c WHERE c.TITLE='Harry Potter and the Chamber of Secrets'),
        1
    );

Execute the queries and see how adding an outer join can help执行查询并查看添加外部联接如何提供帮助

You can see that Malfoy has a loan你可以看到马尔福有一笔贷款

SELECT \
 o.UNID, o.ISBN, \
 c.Title, \
 CONCAT(e.Firstname, ' ', e.Lastname) full_name, \
 CONCAT(e.House, ' ', e.TutorGroup) form, \
 o.StartDate, o.EndDate \
FROM OnLoan o
 INNER JOIN Enrolment e ON o.UNID=e.UNID
 INNER JOIN Catalogue c ON o.ISBN=c.ISBN
WHERE o.OnLoan = 1 
 AND o.EndDate >= NOW()
;
 unid |      isbn      |                  title                  |  full_name   |              form              |         startdate          |          endda
te           
------+----------------+-----------------------------------------+--------------+--------------------------------+----------------------------+---------------
-------------
    4 | 978-0439064873 | Harry Potter and the Chamber of Secrets | Draco Malfoy | Slytherin Snape' Dungeon Group | 2020-05-09 22:31:36.086555 | 2020-05-30 22:
31:36.086555
(1 row)

Delete Malfoy from the System从系统中删除马尔福

DELETE FROM Enrolment WHERE Lastname='Malfoy';
DELETE 1

Run the query again and you cannot seen any loans from Malfoy.再次运行查询,您将看不到 Malfoy 的任何贷款。 He made a clean getaway他做了一个干净的假期

SELECT \
 o.UNID, o.ISBN, \
 c.Title, \
 CONCAT(e.Firstname, ' ', e.Lastname) full_name, \
 CONCAT(e.House, ' ', e.TutorGroup) form, \
 o.StartDate, o.EndDate \
FROM OnLoan o
 INNER JOIN Enrolment e ON o.UNID=e.UNID
 INNER JOIN Catalogue c ON o.ISBN=c.ISBN
WHERE o.OnLoan = 1 
 AND o.EndDate >= NOW()
;
unid | isbn | title | full_name | form | startdate | enddate 
------+------+-------+-----------+------+-----------+---------
(0 rows)

What you need to investigate is outer joins.您需要调查的是外连接。 Inner joins means that a record has to exist in both the left and right hand side of the join to appear.内连接意味着记录必须同时存在于连接的左侧和右侧才能出现。 With the OUTER JOIN you can see that there is a Loan, but the user is gone.使用 OUTER JOIN 可以看到有一个 Loan,但用户已经离开。

SELECT \
 o.UNID, o.ISBN, \
 c.Title, \
 CONCAT(e.Firstname, ' ', e.Lastname) full_name, \
 CONCAT(e.House, ' ', e.TutorGroup) form, \
 o.StartDate, o.EndDate \
FROM OnLoan o
 LEFT OUTER JOIN Enrolment e ON o.UNID=e.UNID
 INNER JOIN Catalogue c ON o.ISBN=c.ISBN
WHERE o.OnLoan = 1 
 AND o.EndDate >= NOW()
;
unid |      isbn      |                  title                  | full_name | form |         startdate          |          enddate           
    ------+----------------+-----------------------------------------+-----------+------+----------------------------+----------------------------
4 | 978-0439064873 | Harry Potter and the Chamber of Secrets |           |      | 2020-05-09 22:31:36.086555 | 2020-05-30 22:31:36.086555
(1 row)

If you want to allow relations that have no match in Enrolment , you can use a left join when bringint that table, and coalesce() to assign default values:如果要允许在Enrolment中不匹配的关系,可以在引入该表时使用left join ,并使用coalesce()分配默认值:

SELECT 
    ol.UNID, 
    ol.ISBN, 
    ca.Title, 
    COALESCE(en.Firstname + ' ' + en.Lastname, 'Uknown User') As FullName, 
    COALESCE(en.House + en.TutorGroup, 'Unknown Form') as Form, 
    ol.StartDate, 
    ol.EndDate 
FROM Catalogue ca
INNER JOIN OnLoan ol ON ol.ISBN = ca.ISBN
LEFT JOIN Enrolment en ON en.UNID = ol.UNID 
WHERE 
    ol.OnLoan = 1 
    and ol.EndDate >= cast(getdate() as date)

Side notes:旁注:

  • do not use single quotes for column aliases - they are meant for string literals - instead, use square brackets (or better yet, use column aliases that do not require quoting)不要对列别名使用单引号 - 它们用于字符串文字 - 而是使用方括号(或者更好的是,使用不需要引用的列别名)

  • nested parentheses around join s are superfluous in SQL Server (only MS Access requires that) join周围的嵌套括号在 SQL 服务器中是多余的(只有 MS Access 需要)

  • table aliases make the query easier to read and write表别名使查询更易于读写

  • no need to use a parameter to get the current date, you can do that directly in the query不需要使用参数来获取当前日期,您可以直接在查询中进行

I did more research and it was full outer join that I wanted, I just kept overlooking it as I kept looking at it wrong.我做了更多的研究,它是我想要的完全外部连接,我只是一直忽略它,因为我一直看错了。

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

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