如何创建使用另一个查询结果的单个MySQL查询

时间:2016-05-09 21:08:10

标签: mysql

我有一个Perl程序,它会查询MySQL数据库,根据哪个"报告"用户从网页中选择的选项。

其中一份报告是学生住房大楼的所有住户,他们申请了停车许可证,但尚未获得停车许可证。

当学生申请许可证时,它会在一个表格行中记录他们的汽车(品牌,型号,年份,颜色等)的细节。每间公寓最多可容纳3名学生,每名学生可申请许可。因此,公寓可能有0个许可证,或1,2或3个许可证,具体取决于其中有多少车辆。

我希望能够做的是,执行一个MySQL查询,找出每个公寓中有多少人占用了停车许可证,然后根据该查询的结果找出已发出多少许可证。如果发出的许可证数量少于申请数量,则应在结果集中返回该公寓号码。它不必为特定的占用者命名,只是公寓至少有一名申请许可但尚未获得许可的人。

所以我有两个表,一个叫occupant_info,它包含有关占用者的各种信息,但相关字段是:

counter (a unique row id)
parking_permit_1_number
parking_permit_2_number
parking_permit_3_number

当指定了停车许可证时,会将其记录在相应的parking_permit_#_number field中(如果它是第1号乘客的许可证,则会记录在parking_permit_1_number等中)。

第二个表名为parking_permits,包含所有汽车/所有者详细信息(品牌,型号,年份,所有者,所有者地址等)。它还包含一个引用occupant_info表中的计数器的字段。

所以一个例子是:

occupant_info表

counter | parking_permit_1_number | parking_permit_2_number | parking_permit_3_number
--------|-------------------------|-------------------------|------------------------
1       | 12345                   |                         | 98765
2       | 43920                   |                         |  
3       | 30239                   |                         | 34233

parking_permits表

counter | counter_from_occupant_info | permit_1_name | permit_2_name   | permit_3_name
--------|----------------------------|---------------|-----------------|-------------------
1       |2                           | David Jones   | James Cameron   | Michael Smerconish
2       |3                           | Bill Epps     | Hillary Clinton | Donald Trump
3       |1                           | Joanne Miller |                 | Sridevi Gupta

我想要一个查询,首先查看公寓中有多少人占用了许可证。这是通过计算parking_permits表中的名称来确定的。在该表中,第1行有三个名称,第2行有三个名称,第3行有两个名称。然后,查询应查看occupant_info表,并从counter_from_occupant_info表中查看每个parking_permits,查看是否已签发相同数量的停车许可证。这可以通过比较非空白parking_permit_#_number字段的数量来确定。

使用上面的数据,查询会看到以下内容:

parking_permit table row 1

Has counter_from_occupant_info equal to "2"
Has three names
The row in occupant_info with counter = "2" has only one permit number issued,
    so counter_from_occupant_info 2 from parking_permits should be in the result set.

parking_permit table row 2

Has counter_from_occupant_info equal to "3"
Has three names
The row in occupant_info with counter = "3" has only two permit numbers issued,
    so counter_from_occupant_info 3 from parking_permits should be in the result set.

parking_permit table row 3

Has counter_from_occupant_info equal to "1"
Has two names
The row in occupant_info with counter = "1" has two permit numbers issued,
    so this row should *not* be in the result set.

我已考虑过使用ifthencasewhentype logic在一个查询中执行此操作,但坦率地说可以& #39;围绕如何做到这一点。

我在想这样的事情:

SELECT 
CASE WHEN ( SELECT counter_from_occupant_info
            FROM parking_permits
            WHERE parking_permit_1_name != ""
              AND parking_permit_2_name != ""
              AND parking_permit_3_name != "" ) THEN 
IF ( SELECT parking_permit_1_number,
            parking_permit_2_number,
            parking_permit_3_number
     FROM occupant_info
     WHERE counter = ***somehow reference counter from above case statement--I don't know how to do this*** 

然后我的脑袋爆炸了,我意识到我不知道我在做什么。

任何帮助将不胜感激。 : - )

    Doug

1 个答案:

答案 0 :(得分:1)

你有一些问题:

  1. 您的占用者表架构很糟糕。那里的情况更糟,但看起来有些人并不了解数据库的工作原理。

  2. 您的许可表也很糟糕。同样的原因。

  3. 你不知道自己在做什么(开玩笑......开玩笑......)

  4. 问题1:

    您的居住者表应该是两张桌子。因为占用者可能有0-3个许可证(可能更多,我无法从样本数据中得知),那么您需要一个表格来显示您的占用者的属性(姓名,身高,性别,年龄,主要气味,最喜欢的颜色,第一次租赁日期,我不知道)。

    乘员

    OccupantID | favorite TV Show | number of limbs | first name | last name | aptBuilding
    

    并且......占用者和许可证之间关系的另一个表格:

    Occupant_permits

    OccupantID | Permit ID | status
    

    现在......占用者可以拥有尽可能多的许可证,并且他们之间的关系具有状态"申请"或"授予"或"撤销"或者你有什么。

    问题2

    你的许可证信息表也是双重职责。它包含有关许可证(它的名称)以及与占用者的关系的信息。因为我们已经与" Occupant_Permits"上面的表格,我们只需要一张许可证表来保存许可证的属性:

    许可证

     Permit ID | Permit Name | Description | etc..
    

    问题3

    现在你有一个正确的架构,其中的对象在他们自己的表中(占用者,许可证,占用者和许可证关系)你的查询得到一个公寓列表,其中至少有一个占用者已经申请但尚未收到许可证将是:

    SELECT
        COUNT(DISTINCT o.AptBuilding)
    FROM 
        occupants as o
        INNER JOIN occupants_permit as op 
            ON o.occupant_id = op.occupant_id
        INNER JOIN permits as p 
            ON op.permit_id = p.permit_id
    WHERE
        op.Status = "Applied"
    

    这很简单,你不依赖CASEUNION或计算比较或任何花哨的东西。只是很好的直接连接和一个简单的WHERE子句。这将是快速查询,并没有有趣的业务。

    因为您的架构不是很好,为了获得类似的东西,您需要使用UNION查询将许多permit_N_字段堆叠到单个字段中并运行类似于上述查询的内容,或者您将使用相当数量的CASE / IF声明:

    SELECT DISTINCT p.pCounter
    FROM
        (
            SELECT
                counter as Ocounter
                CASE WHEN parking_permit_1_number IS NOT NULL THEN 1 ELSE 0 END
                +
                CASE WHEN parking_permit_2_number IS NOT NULL THEN 1 ELSE 0 END
                +
                CASE WHEN parking_permit_3_number IS NOT NULL THEN 1 ELSE 0 END AS permitCount
            FROM occupant_info
        ) as o
        LEFT OUTER JOIN
        (
            SELECT
                counter_from_occupant_info as pCounter
                CASE WHEN parking_permit_1_name IS NOT NULL THEN 1 ELSE 0 END
                +
                CASE WHEN parking_permit_2_name IS NOT NULL THEN 1 ELSE 0 END
                +
                CASE WHEN parking_permit_3_Name IS NOT NULL THEN 1 ELSE 0 END AS permitPermitCount
        ) as p ON o.Ocounter = p.Pcounter
    
    WHERE p.permitCounter > o.PermitCount
    

    我并非100%确信这正是您正在寻找的,因为您的架构令人困惑,因为您在一个表中有多个对象并且所有内容都是旋转的,但是......它应该让您在球中公园。

    这也会慢得多。有中间结果集,CASE语句和数学,所以不要指望MySQL在几毫秒内吐出这个。

相关问题