如何编写简单的选择查询而不是使用视图?

Ofe*_*Ron 4 mysql sql view

找到在同一天访问过两位同一专业的不同医生的患者.

示例数据库:单击此处查看SQL Fiddle中的示例数据脚本.

CREATE VIEW DistinctVisits AS
SELECT v.vid,v.pid,d.speciality,v.date
FROM Visits v ,Doctors d
WHERE d.did=v.did
GROUP BY v.pid,v.did,v.date;

CREATE VIEW DistinctVisits2 AS
SELECT dv.pid,dv.speciality,dv.date, COUNT(dv.vid) as countv
FROM DistinctVisits dv
GROUP BY dv.pid,dv.speciality,dv.date;

SELECT dv2.pid,dv2.speciality
FROM DistinctVisits2 dv2
WHERE dv2.countv=2;

DROP VIEW DistinctVisits;
DROP VIEW DistinctVisits2;
Run Code Online (Sandbox Code Playgroud)

我如何重复相同的想法,但只是一个大问题?另外一个解决方案也会很好,但请尽量帮助我改进这个.

小智 7

说明:

  • 您需要找到在某一天访问过两位不同医生的患者名单.

  • 在此要求中,您的Patient表成为主表.我们先查询该表.

  • 现在我们有患者名单.我们需要获得他们访问过的医生名单.我们不能简单地将Patients表与Doctors表一起加入,因为没有列来映射数据.我们必须使用Visits作为中间表

  • LEFT OUTER JOIN在患者和访问表之间添加一个并按pid列加入.

  • 我们有病人和他们的访问清单,但现在我们需要得到医生的信息.因此,LEFT OUTER JOIN在Visits和Doctors表之间添加另一个并通过did列加入.

  • 我们有患者和医生访问信息.但是,我们只需要患者的姓名,他们所访问的医生的专长以及他们访问的日期.因此,我们将添加列p.pname,d.specialityv.dateSELECT子句也是在GROUP BY子句.除此之外,我们需要所有的访问次数,但有一个问题.我们只需要DISTINCT计数,换句话说,我们需要他们访问过的所有独特医生的数量.因此,如果患者在给药日两次访问同一位医生,则应将其计为1.因此,添加DISTINCT将有助于此处.另外,关键是使用正确的列名,在这种情况下,d.did代表医生.

  • 我们拥有所需的所有数据,但我们只需要过滤同一天访问过两位不同医生的患者.要做到这一点,HAVING条款来解救我们.当您应用GROUP BY时,HAVING是合适的.我们将使用相同的COUNT(DISTINCT d.did)来检查计数是否仅匹配值2.您可以在输出中查看结果.

建议:

  • 您不必为插入表中的每个值指定INSERT INTO语句.您可以在括号内将它们组合在一起并将它们分开commas.最后一个陈述应该结束semicolon.

  • 查询使用LEFT OUTER JOIN.我使用这个联合来找出每个病人的所有医生就诊,即使他们从未去过医生.我只是想在我形成查询时看到输出.您可以将其更改为INNER JOIN,我认为在您的方案中更合适.

  • 如果您不想显示访问次数,可以将其从SELECT子句中删除.

演示:

单击此处查看SQL Fiddle中的演示.

用于解释的脚本:

SELECT          p.pname
            ,   d.speciality 
            ,   v.date
            ,   COUNT(DISTINCT d.did) AS visitcount
FROM            Patient p
LEFT OUTER JOIN Visits v
ON              v.pid = p.pid
LEFT OUTER JOIN Doctors d
ON              d.did = v.did
GROUP BY        p.pname
            ,   d.speciality
            ,   v.date
HAVING          COUNT(DISTINCT d.did) = 2
Run Code Online (Sandbox Code Playgroud)

更合适的脚本:

SELECT      p.pname
        ,   d.speciality 
        ,   v.date
FROM        Patient p
INNER JOIN Visits v
ON          v.pid = p.pid
INNER JOIN Doctors d
ON          d.did = v.did
GROUP BY    p.pname
        ,   d.speciality
        ,   v.date
HAVING      COUNT(DISTINCT d.did) = 2
Run Code Online (Sandbox Code Playgroud)

输出:

PNAME      SPECIALITY    DATE       VISITCOUNT
---------  ------------  ---------  -----------
Loch Ness  Assholes      17/9/2012      2
Loch Ness  Orthopedist   13/1/2011      2
Run Code Online (Sandbox Code Playgroud)

创建表并插入脚本:

create table InsuranceCompanies  (
    cid         int,
    cname       varchar(20),
    primary key (cid)
);

create table Patient (
    pid         int,
    pname       varchar(20),
    age         int,
    cid         int,
    gender      char,
    primary     key (pid),
    constraint foreign key (cid) 
        references InsuranceCompanies (cid) 
);

create table Doctors (
    did         int ,
    dname       varchar(20),
    speciality  varchar(20),
    age         int,
    cid         int,
    primary key (did),
    constraint foreign key (cid) 
        references InsuranceCompanies (cid) 
);

create table Visits(
    vid         int,
    pid         int,
    did         int,
    date        varchar(20),
    primary key (vid),
    constraint foreign key (pid) 
        references Patient (pid) ,
    constraint foreign key (did) 
        references Doctors (did)
);

INSERT INTO InsuranceCompanies(cid, cname) VALUES
    ( 1111, 'Harel Inc' ),
    ( 2222, 'Clalit Inc' );

INSERT INTO Doctors ( did, dname, speciality, age, cid) VALUES 
    ( 100, 'Jhonny Depp',       'Heart',        42, 1111 ),
    ( 101, 'Tom Tolan',         'Assholes',     62, 1111 ),
    ( 105, 'Yom Tov',           'Assholes',     52, 1111 ),
    ( 102, 'Lauren Jaime',      'Throat',       27, 2222 ),
    ( 103, 'Gomez Flaurence',   'Legs',         37, 2222 ),
    ( 106, 'David Harpaz',      'Orthopedist',  37, 2222 ),
    ( 107, 'David Schwimmer',   'Orthopedist',  37, 2222 ),
    ( 108, 'Sammy Salut',       'Orthopedist',  37, 1111 );

INSERT INTO Patient ( pid, pname, age, cid,gender) VALUES 
    ( 200, 'Jon Gilmour',       25, 2222, 'm' ),
    ( 206, 'Bon Gilmour',       30, 2222, 'm' ),
    ( 205, 'Jon Gilmour',       22, 2222, 'm' ),
    ( 201, 'Bon Jovy',          21, 2222, 'm' ),
    ( 202, 'Loch Ness',         17, 2222, 'f' ),
    ( 203, 'Lilach Sonin',      12, 1111, 'f' ),
    ( 209, 'Lilach Dba',        34, 1111, 'f' ),
    ( 210, 'Paulina Daf',       32, 1111, 'f' ),
    ( 204, 'Gerry Jalor',       23, 1111, 'm' ),
    ( 208, 'Jerrushalem Jalor', 23, 1111, 'm' );

INSERT INTO Visits ( vid, pid, did, date) VALUES 
    ( 300, 204, 100,    '12/12/2012' ),
    ( 301, 204, 101,    '12/12/2012' ),
    ( 302, 204, 101,    '02/01/2012' ),
    ( 303, 202, 101,    '17/09/2012' ),
    ( 311, 202, 105,    '17/09/2012' ),
    ( 304, 203, 102,    '12/12/2011' ),
    ( 312, 202, 106,    '13/06/2012' ),
    ( 314, 202, 107,    '13/01/2011' ),
    ( 313, 202, 108,    '13/01/2011' ),
    ( 305, 204, 102,    '10/10/2011' ),
    ( 306, 201, 100,    '12/01/2012' ),
    ( 316, 204, 108,    '18/05/2012' ),
    ( 307, 202, 100,    '12/07/2012' ),
    ( 315, 203, 108,    '12/07/2012' ),
    ( 310, 204, 103,    '10/04/2012' ),
    ( 308, 203, 102,    '12/12/2011' ),
    ( 309, 200, 101,    '12/12/2012' );
Run Code Online (Sandbox Code Playgroud)