【问题标题】:Select query to retrieve results based on multiple values for a one column (AND condition)选择查询以根据一列的多个值检索结果(AND 条件)
【发布时间】:2014-05-10 02:09:23
【问题描述】:

如下三张表

表 1 - 车辆

Vehicle_Id 主键
名称
序列号

表 2 - 属性名称

Property_Id 主键
名称

表 3 - 属性

Property_Id (FOREIGN KEY) 引用 Propertyname 表中的 Property_Id
价值
Id (FOREIGN KEY) 引用 Vehicle 表中的 Vehicle_Id

样本数据

表 1 - 车辆

Vehicle_Id 名称 Serial_Number 
1000 WagonR Maruti-WagonR 
1001 Estilo Maruti-Estilo 
1002 Zen Maruti-Zen 

表 2 - 属性名称

Property_Id 名称
100 里程 
101 燃料类型
102 个国家 

表 3 - 属性

Property_Id 值 ID 
100 50 1000 
101 汽油 1000 
102 印度 1000 
100 35 1001 
101 柴油机 1002 

从三个表中我们可以看到,每辆车都有一组属性,这些属性在属性表中保存为行。这样做是为了如果我们向车辆添加更多属性,我们会为车辆添加行条目,而不是添加不可行的列。

现在我有了一个 UI,我可以在其中根据车辆搜索车辆

1) 名称、序列号 - 这些可作为车辆表中的列 &
2) Mileage、FuelType、Country - 这些是特定车辆的属性

用户可以输入上述 1) 和 2) 中的任意值组合来搜索车辆列表。

例如:- 如果用户输入 Mileage 为 50 且 FuelType 为 Diesel,我应该获取 Mileage 为 50 且 FuelType 为 Diesel 的车辆的结果。

我尝试了下面的 SQL 语句来做同样的事情

select vh.Vehicle_Id, vh.name, pt.Property_Id, pn.name, pt.value
from property pt
inner join propertyname pn
on pt.Property_Id=pn.Property_Id
inner join vehicle vh
on vh.Vehicle_Id=pt.Id
and ((pn.Name='Mileage' AND pt.Value='50') AND (pn.Name='FuelType' AND pt.Value='Petrol'));

但由于单行结果的 AND 条件,我得到零结果。但是,如果我将最后一个 AND 条件更改为 OR,我会得到两个符合条件的结果。

但我正在尝试获取与两个属性匹配的车辆。

我尝试过使用 INTERSECT、两条 SQL 语句的内连接等。但无法得到结果。

谁能建议我搜索两个属性名称、值对的最佳方法,它们以行而不是列的形式存在,以获得准确的搜索结果。

【问题讨论】:

  • 您需要重新考虑数据库的设计。表 3 中名为“值”的列存储了里程和燃料类型值。所以最好为这些值使用两个不同的列,然后尝试。
  • 感谢您的回复。目前无法进行数据库设计。车辆的属性也可以随时添加

标签: java sql sql-server


【解决方案1】:

您的问题是 PropertyName 不能同时是“Mileage”和“FuelType”

你可以像这样在两个propertyNames的交叉点找到id所在的所有车辆

select Vehicle_Id, Vehicle.Name, Serial_Number, PropertyName.Name, Property.Value
from Vehicle
join Property on (Property.Id = Vehicle.Vehicle_Id)
join PropertyName on (PropertyName.Property_Id = Property.Property_Id)
where Vehicle_id in 
(select Id 
    from PropertyName 
    Join Property on (PropertyName.Property_Id = Property.Property_Id)
    where PropertyName.Name = 'Mileage' and Property.Value = '50'
 intersect 
 select Id 
    from PropertyName 
    Join Property on (PropertyName.Property_Id = Property.Property_Id)
    where PropertyName.Name='FuelType' AND Property.Value='Petrol'
 )


Vehicle_Id  Name    Serial_Number   Name    Value
1000    WagonR  Maruti-WagonR   Mileage 50
1000    WagonR  Maruti-WagonR   FuelType    Petrol
1000    WagonR  Maruti-WagonR   Country India

【讨论】:

    【解决方案2】:

    有很多方法

    我会做这样的事情

    select vh.Vehicle_Id, pt_m.value as [Mileage], pt_f.value as [FuelType]
    from vehicle vh
    inner join propertyname pn_m ON pn_m.Name='Mileage'
    inner join propertyname pn_f ON pn_f.Name='FuelType' 
    inner join property     pt_m on pt_m.Property_Id=pn_m.Property_Id AND pt_m.Id = vh.Vehicle_Id
    inner join property     pt_f on pt_f.Property_Id=pn_f.Property_Id AND pt_f.Id = vh.Vehicle_Id
    

    在加入两个属性时,属性名称表需要两个别名,并且属性值同样需要两个别名

    这样做的一个好处是 它可以快速适应处理其中一个属性实际上没有填充的车辆

    select vh.Vehicle_Id, pt_m.value as [Mileage], pt_f.value as [FuelType]
    from vehicle vh
    left join propertyname pn_m ON pn_m.Name='Mileage'
    LEFT join propertyname pn_f ON pn_f.Name='FuelType' 
    LEFT join property     pt_m on pt_m.Property_Id=pn_m.Property_Id AND pt_m.Id = vh.Vehicle_Id
    LEFT join property     pt_f on pt_f.Property_Id=pn_f.Property_Id AND pt_f.Id = vh.Vehicle_Id
    

    甚至处理不一致的属性名称

    select vh.Vehicle_Id, pt_m.value as [Mileage], pt_f.value as [FuelType]
    from vehicle vh
    left join propertyname pn_m ON pn_m.Name='Mileage'
    LEFT join propertyname pn_f ON pn_f.Name IN ('FuelType','Fuel Type') 
    LEFT join property     pt_m on pt_m.Property_Id=pn_m.Property_Id AND pt_m.Id = vh.Vehicle_Id
    LEFT join property     pt_f on pt_f.Property_Id=pn_f.Property_Id AND pt_f.Id = vh.Vehicle_Id
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-26
      • 2023-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多