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

时间:2020-05-09 21:40:47

标签: sql sql-server vb.net tsql join

我正在创建一个图书馆管理系统。

我正在尝试通过带有内部联接功能的VB.NET查询SQL数据库,并将数据返回到datagridview,我正在寻找的是返回某种东西,我不知道进行下一步的最佳方法。 / p>

我有一个名为 Onloan 的表,其中包含有关贷款的基本信息,用户 UNID 的ID,书的ISBN,开始日期和结束日期以及返回日期,然后内部与登记表(对于用户)和目录表(对于帐簿)结合在一起,以创建有关什么贷款有效,针对谁和谁的完整图片,但是我在程序上具有重置功能,允许管理员或高级图书馆员重置特定表(例如,用户表),但当前代码不会显示任何结果,因为用户表为空,显然这不会因为我使用的语句而导致,这意味着仪表板不会是正确的

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") & "' )

该图像用于onloan和过期的datagrid中的仪表板,即使数据未完成,我也需要信息。只需在此处放置“未知用户”或其他内容即可。

image of dashboard

我只想要我应该查看的领域的信息和参考,如果您能够编辑我的代码并让我使用它,那太好了,但是您可以提供的任何信息和帮助将不胜感激。

3 个答案:

答案 0 :(得分:3)

您需要调查外部联接。这些类型的JOINS将从特定方面返回JOIN的所有结果,无论另一个表中是否有匹配项。我在postgres中创建了您的表格,然后运行了它。

表格创建

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

用数据播种表

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

执行查询,了解添加外部联接有何帮助

您可以看到Malfoy有一笔贷款

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)

从系统中删除Malfoy

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

再次运行查询,您将看不到Malfoy的任何贷款。他干净利落

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)

您需要研究的是外部联接。内部联接意味着要在联接的左侧和右侧都必须存在一条记录。使用OUTER JOIN,您可以看到有一笔贷款,但是用户已经走了。

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)

答案 1 :(得分:0)

如果要允许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)

旁注:

  • 不要对列别名使用单引号-它们用于字符串文字-而是使用方括号(或者更好的是,使用不需要引用的列别名)

  • 在SQL Server中,在join周围的
  • 嵌套括号是多余的(仅MS Access要求这样做)

  • 表别名使查询更易于读写

  • 无需使用参数即可获取当前日期,您可以直接在查询中完成

答案 2 :(得分:0)

我做了更多的研究,这是我想要的完全外部联接,因为我一直认为它是错误的,所以我只是忽略了它。