代码之家  ›  专栏  ›  技术社区  ›  Yanayaya

如何构造SQL查询以防止返回带有相关数据的重复行?

  •  -1
  • Yanayaya  · 技术社区  · 6 年前

    我需要一些关于SQL查询的帮助。我有一个数据库表,其中包含与其他表相关的数据。当我查询表时,它会返回每一行相关数据的重复行,即

    |-------------|           |-------------|           |-------------|
    | Cars        |           | Options     |           | Value       |
    |-------------|  ------>  |-------------|  ------>  |-------------|
    | CarId       |           | OptionsId   |           | ValueId     |
    | CarMake     |           | OptionName  |           | CostValue   |
    | CarModel    |           | Confirmed   |           | CarId       |
    |-------------|           | CarId       |           | OptionsId   |
                              |-------------|           |-------------|
            |
            |
            --------------->  |-------------|
                              | Warranty    |
                              |-------------|
                              | WarrantyId  |
                              | WarrantyType|
                              | CarId       |
                              |-------------|
    

    我所做的查询是在SSMS的查询生成器中设计的(因为它不使用别名,并且具有三阶段命名约定,这将被更改),如下所示:

    SELECT dbo.Cars.CarId, 
           dbo.Cars.Make, 
           dbo.Cars.Model, 
           dbo.Options.OptionName, 
           dbo.Warranty.WarrantyType,
           dbo.Value.CostValue
    FROM   dbo.Cars 
           LEFT JOIN dbo.Options ON dbo.Cars.CarId = dbo.Options.CarId 
           LEFT JOIN Value ON Options.OptionsId = Value.OptionsId 
           LEFT JOIN dbo.Warranty on dbo.Cars.CarId = dbo.Warranty.CarId
    

    执行这个查询时返回我的数据,但是,对于有多个选项的汽车,我会收到重复的行,即。

    Id | Make | Model  | Option Name      | Warranty Type | Value  
    27 | Ford | Fiesta | Heated Seats     | Static        | 500
    27 | Ford | Fiesta | Front Fog Lights | Static        | 400
    

    我一直在寻找这个问题的可能答案,发现建议的解决方案是使用关键字 DISTINCT 或者创建子查询。我补充说 独特的 但返回了相同的数据,可能是因为选项本身是不同的,我不知道我在猜测。

    我很乐意使用子查询,但不确定如何将其应用于我的上述查询代码。这里我要做的就是为每辆车返回一行选项值最高的值,即。

    27 | Ford | Fiesta | Heated Seats  |  Static  | 500
    

    有人能帮我写这个问题吗?我想我已经把所有问题都包括在内了,但是如果我能提供更多,请告诉我。

    2 回复  |  直到 6 年前
        1
  •  1
  •   forpas    6 年前

    而不是加入表格 Value 它给你多行,
    必须加入此查询:

    SELECT 
      dbo.Value.CarId, 
      dbo.Value.OptionsId, 
      MAX(dbo.Value.CostValue) AS CostValue
    FROM dbo.Value
    GROUP BY dbo.Value.CarId, dbo.Value.OptionsId 
    

    从桌子上给你的 价值 对于每辆车,选择最大值。
    所以试试这个:

    SELECT dbo.Cars.CarId, 
           dbo.Cars.Make, 
           dbo.Cars.Model, 
           dbo.Options.OptionName, 
           v.CostValue,
           dbo.Warranty.WarrantyType
    FROM   dbo.Cars 
           LEFT JOIN dbo.Options ON dbo.Cars.CarId = dbo.Options.CarId 
           INNER JOIN (
                      SELECT 
                      dbo.Value.CarId, 
                      dbo.Value.OptionsId, 
                      MAX(dbo.Value.CostValue) AS CostValue
                      FROM dbo.Value
                      GROUP BY dbo.Value.CarId, dbo.Value.OptionsId  
           ) AS v ON Options.OptionsId = v.OptionsId 
           LEFT JOIN dbo.Warranty on dbo.Cars.CarId = dbo.Warranty.CarId
    
        2
  •  0
  •   Zaynul Abadin Tuhin    6 年前

    您可以使用window函数尝试如下操作

     with cte as(
               SELECT    dbo.Cars.CarId, 
               dbo.Cars.Make, 
               dbo.Cars.Model, 
               dbo.Options.OptionName, 
               Value.CostValue,
               row_number() over(partition by dbo.Cars.CarId, 
               dbo.Cars.Make, 
               dbo.Cars.Model order by Value.CostValue desc) rn   
        FROM   dbo.Cars 
               LEFT JOIN dbo.Options ON dbo.Cars.CarId = dbo.Options.CarId 
               LEFT JOIN Value ON Options.OptionsId = Value.OptionsId 
               LEFT JOIN dbo.Warranty on dbo.Cars.CarId = dbo.Warranty.CarId
              ) select * from cte where rn=1