从DB获取特定记录

时间:2017-10-29 09:17:33

标签: sql sql-server sql-server-2012

我有以下表格和值:



t_cars
---------------------------------------------------------
nCars_ID	sName		sModel		sIdentifier	
---------------------------------------------------------
1		BMW		3 series	D-78-JHG
2		Volvo		C30		B-56-KHT
3		Fiat		Doblo		H-72-ABN
4		Volvo		C40		J-78-YTR


t_feature
---------------------------
nFeature_ID		sName
---------------------------
1			CMC
2			Doors
3			Color
4			Type
5			Weight
6			Engine
7			Power


t_cars_feature
-------------------------------------------------------------------
nCarsFeature_ID	nCars_ID	nFeature_ID		sValue
------------------------------------------------------------------
1		2		1			2500
2		2		2			5
3		2		4			Diesel
4		2		3			Green
5		3		1			1900
6		3		2			3
7		3		4			Otto
8		3		5			2300 KG
9		1		1			1900
10		1		3			Blue
11		1		4			Diesel
12		1		5			2100 KG




我需要从DB中检索具有CMC功能的汽车,具有颜色功能,并且CMC = 1900和颜色='蓝色' ONLY

我试过了:

SELECT t_cars.sName, t_cars.sModel, t_cars.sIdentifier 
FROM t_cars, t_feature, t_cars_feature 
WHERE t_feature.nFeature_ID = t_cars_feature.nFeature_ID 
AND t_cars.nCars_ID = t_cars_feature.nCars_ID
AND [/*condition that get me cars that has CMC feature, has Color feature, AND CMC = 1900 AND Color = 'Blue' ONLY*/]

我尝试过这样的条件: 试用1:

AND t_feature.sName = 'CMC'
AND t_feature.sName = 'Color'
AND t_cars_feature.sValue = '1900'
AND t_cars_feature.sValue = 'Blue'

并没有给我任何东西

我也尝试过: 试用2:

AND t_feature.sName IN ('CMC','Color')
AND t_cars_feature.sValue IN ('1900','Blue')

并告诉我所有记录有CMC 1900或颜色'蓝' (可能我来这里是笛卡尔产品)

在实际情况中,我可以有几个t_feature.sName值和几个t_cars_feature.sValue值,这就是为什么试用1不适合我 ...

你能帮帮我吗?谢谢。

3 个答案:

答案 0 :(得分:3)

使用此查询:

SELECT *
FROM   t_cars        
WHERE EXISTS (SELECT * FROM t_cars_feature AS cf 
                       JOIN t_feature AS f ON (f.nFeature_ID = cf.nFeature_ID)
              WHERE t_cars.nCars_ID = cf.nCars_ID AND f.sName = 'CMC' AND cf.sValue = '1900')     
      AND 
      EXISTS (SELECT * FROM t_cars_feature AS cf 
                       JOIN t_feature AS f ON (f.nFeature_ID = cf.nFeature_ID)
              WHERE t_cars.nCars_ID = cf.nCars_ID AND f.sName = 'Color' AND cf.sValue = 'Blue');

See the full example here.

我想对你在那里做过的一些事情发表评论:

  • 通常认为将类型标注为列名称或对象名称中的前缀是不好的做法。
  • 您对IN子句的使用是错误的。我建议你尝试一下这个问题。当您在IN子句中提供值列表时,这意味着任何这些值都应该为谓词生成一个真值 - 而不是它们都应该存在。
  • 请注意,当您使用WHERE子句将多个谓词分隔为" AND"时,您需要所有谓词都存在于SINGLE行中。查看JOIN的结果,看看是否能够更好地理解这种情况。
  • 使用JOIN(即INNER JOIN)而不是笛卡尔积(())被认为是更好的做法 - 即使两个查询通常都会编译到同一个执行计划中。它更具可读性和可理解性。

答案 1 :(得分:1)

您可以使用EXISTS而不是EXISTS:

--Alias = Table
--    C = t_cars
--   CF = t_cars_feature
--    F = t_feature

SELECT * 
  FROM t_cars C
 WHERE EXISTS (SELECT *
                 FROM t_cars_feature CF INNER JOIN t_feature F ON CF.nFeature_ID = F.nFeature_ID
                WHERE CF.nCars_ID = C.nCars_ID --matches t_cars ID 
                  AND F.sName = 'CMC' --has CMC feature
                  AND F.sName = 'Color' --has color feature
                  AND CF.sValue = '1900'  --CMC = 1900 
                  AND CF.sValue = 'Blue'  --Color = 'Blue'
              )
   AND NOT EXISTS 
              (SELECT *
                 FROM t_cars_feature CF INNER JOIN t_feature F ON CF.nFeature_ID = F.nFeature_ID
                WHERE CF.nCars_ID = C.nCars_ID --matches t_cars ID 
                  AND F.sName = 'CMC' --has CMC feature
                  AND F.sName = 'Color' --has color feature
                  AND CF.sValue = '1900'  --CMC = 1900 
                  AND CF.sValue <> 'Blue'  --Color = 'Blue ONLY'
              )

答案 2 :(得分:0)

您可以使用条件聚合来获得所需的结果

SELECT t_cars.sName, t_cars.sModel, t_cars.sIdentifier 
FROM t_cars
JOIN t_cars_feature  ON t_cars.nCars_ID = t_cars_feature.nCars_ID 
JOIN t_feature ON t_feature.nFeature_ID = t_cars_feature.nFeature_ID 
WHERE t_feature.sName IN ('CMC','Color')
GROUP BY t_cars.sName, t_cars.sModel, t_cars.sIdentifier
HAVING SUM(CASE WHEN t_feature.sName ='CMC' AND t_cars_feature.sValue ='1900' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN t_feature.sName ='Color' AND t_cars_feature.sValue ='Blue' THEN 1 ELSE 0 END) >0

Demo