从SQL的四个相关表中获取最小值

时间:2019-04-24 19:41:47

标签: mysql sql

我有几个问题,

首先,当我阅读一些文章时,我知道我将在此问题中使用内部联接来实现SQL代码。 我在 以下:

医院表:

    id  |  hospital_name | adress  | city_id
   -------------------------------------------
    1   | pars           |   55,6LA|   2
    2   | ghaem          |   12.9GI|   2
    3   | Mehr           |   632.Sp|   2
    4   | Erfan          |   21,6UJ|   3
    5   | Razavi         |   31.jjI|   3
    6   | Mohab          |   65.Spi|   1

城市表:

    id  |  cityname 
   --------------------
    1   | LosAngels
    2   | NewYork
    3   | Colifornia

治疗表:

    id  |  TreatmentName 
   ----------------------
    1   | nose surgery   
    2   | Orthopedic  
    3   | Knee joint replacement

治疗价格表:

    id  |  Treatments_id | Hospital_id  | Price
   ------------------------------------------
    1   |       1        |       1      |   700
    2   |       1        |       6      |   800
    3   |       1        |       4      |   900
    4   |       2        |       1      |   500
    5   |       2        |       2      |   700
    6   |       2        |       3      |   300
    7   |       3        |       1      |   600
    7   |       3        |       2      |   450

我的问题是如何按城市代码找到每家医院的最低治疗价格。

如果城市ID 2 ,我需要在表视图中添加以下内容:

    price  |  hospital_name | treatment_name| 
   -------------------------------------------
    700    | pars           |   nose surgery   
    300    | Mehr           |   Orthopedic     
    450    | ghaem          |   Knee joint replacement     

这是我的 SQL 代码:

SELECT Min(treatment_prices.dollar) AS price, 
       hospitals.name_en            AS hname, 
       treatments.title_en          AS title 
FROM   treatment_prices 
       INNER JOIN hospitals 
               ON hospitals.id = treatment_prices.hospital_id 
       INNER JOIN treatments 
               ON treatments.id = treatment_prices.treatment_id 
WHERE  hospitals.city_id = 2 
GROUP  BY treatment_prices.treatment_id 

*但是效果不佳。像下面的照片: Result of my SQL code

任何帮助将不胜感激。*

3 个答案:

答案 0 :(得分:1)

您正在寻找哪种方法在城市的哪家医院中最便宜。

在MySQL 5.x中,您必须使用一些内部子查询来按医院查找最便宜的程序,然后再次将其重新连接到表中以获取所需的数据。

有关设置,请参见小提琴。

SQL Fiddle

MySQL 5.x

首先,您想要找到一个过程的最便宜价格,并根据您所需要的城市和该城市中的医院进行过滤。

查询1

SELECT tp.Treatments_ID, min(tp.Price) AS price
FROM treatment_prices tp
INNER JOIN Hospital h ON tp.Hospital_ID = h.ID
  INNER JOIN Cities c ON h.city_id = c.id
    AND c.ID = 2
GROUP BY tp.Treatments_ID 

这给你

Results

| Treatments_ID | price |
|---------------|-------|
|             1 |   700 |
|             2 |   300 |
|             3 |   450 |

现在,您可以将其用作子查询来再次链接回主表,以检索所需的数据。

查询2

SELECT t2.TreatmentName, h2.Hospital_Name, s1.Price
FROM (
    SELECT tp.Treatments_ID, min(tp.Price) AS price
    FROM treatment_prices tp
    INNER JOIN Hospital h ON tp.Hospital_ID = h.ID
      INNER JOIN Cities c ON h.city_id = c.id
        AND c.ID = 2
    GROUP BY tp.Treatments_ID 
) s1
INNER JOIN treatment_prices tp2 ON s1.Treatments_ID = tp2.Treatments_ID
    AND s1.price = tp2.Price
INNER JOIN Hospital h2 ON tp2.Hospital_ID = h2.ID
INNER JOIN Treatments t2 ON tp2.Treatments_ID = t2.ID

Results

|          TreatmentName | Hospital_Name | Price |
|------------------------|---------------|-------|
|           nose surgery |          pars |   700 |
|             Orthopedic |          Mehr |   300 |
| Knee joint replacement |         ghaem |   450 |

在更高版本的MySQL或允许窗口功能的任何其他SQL语言中,这要容易得多。

MySQL 8 +

SELECT s1.TreatmentName, s1.Hospital_Name, s1.Price
FROM (
    SELECT t.TreatmentName, h.Hospital_Name, tp.Price
        , ROW_NUMBER() OVER (PARTITION BY tp.Treatments_ID ORDER BY tp.Price) AS rn
    FROM treatment_prices tp 
    INNER JOIN Hospital h ON tp.Hospital_ID = h.ID
    INNER JOIN Cities c ON h.city_id = c.id
            AND c.ID = 2
    INNER JOIN Treatments t ON tp.Treatments_ID = t.ID
) s1
WHERE rn = 1
;

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=9b28f7543c3b127990654ad9e401c11a

答案 1 :(得分:0)

您应该使用GROUP BY hospitals.name_en,treatments.title_en

SELECT Min(treatment_prices.dollar) AS price, 
       hospitals.name_en            AS hname, 
       treatments.title_en          AS title
FROM   treatment_prices 
       INNER JOIN hospitals 
               ON hospitals.id = treatment_prices.hospital_id 
       INNER JOIN treatments 
               ON treatments.id = treatment_prices.treatment_id 
WHERE  hospitals.city_id = 2 
GROUP  BY hospitals.name_en  ,  treatments.title_en     

要获得最低费用(价格)应为

select  t.price, t.title, hospitals.name_en   

from (
  SELECT Min(treatment_prices.dollar) AS price, 
         treatments.title_en          AS title,
         treatment_prices.treatment_id 
  FROM   treatment_prices 
         INNER JOIN hospitals 
                 ON hospitals.id = treatment_prices.hospital_id 
         INNER JOIN treatments 
                 ON treatments.id = treatment_prices.treatment_id 
  WHERE  hospitals.city_id = 2 
  GROUP  BY  treatments.title_en, treatment_prices.treatment_id
) t 
INNER JOIN treatments ON treatments.id = treatment_prices.treatment_id  
    AND treatments.title_en   = t.title 
INNER JOIN hospitals  ON hospitals.id = treatment_prices.hospital_id   
    AND treatment_prices.dollar = t.price     

答案 2 :(得分:0)

它没有显示医院应该这样做,因为您只有GROUP BYtreatment_id,当您选择具有聚合功能的列并且DBMS不将其包括在组中时,它将散布第一行的该列到它获取的所有行的结果。因此,首先按treatment_id分组,然后按hospital_name(或ID)分组,然后应该这样做。这样保留查询:

   SELECT Min(tp.dollar) AS price, 
          h.name_en      AS hname, 
          t.title_en     AS title 
    FROM   treatment_prices AS tp
           INNER JOIN hospitals AS h
                   ON h.id = tp.hospital_id 
           INNER JOIN treatments AS t 
                   ON t.id = tp.treatment_id 
    WHERE  h.city_id = 2 
    GROUP  BY tp.treatment_id, hname

请注意,我在h.name_en中为GROUP BY使用了别名,MySQL 8+对此没有任何问题,并且将别名用于视觉效果之外。

还有最后一件事,并且由于我看到其他问题建议使用子查询,因此仅在有必要100%并且没有其他方法时才使用它们。这是因为子查询会针对未在数据库中建立索引且未进行规范化的表创建查询,因此,如果子查询返回的表中的数据过多,则完成查询的时间将比没有子查询时完成查询的时间长得多。也许这对学习或学习没有太大影响,但在工作环境中时间至关重要,因此向部门提供的许多报告提供数据的查询需要快速且最佳。