2014-01-16 30 views
1

我真的想自己想出这个解决方案,但事实证明这比我想象的要稍微复杂一些。有条件的地方;对于SQLServer2008 SQL查询/ TSQL

我试图检索信息的表格看起来像下面的简单形式。

表:CarFeatures

+---+---+---+---+-----+ 
|Car|Nav|Bth|Eco|Radio| 
+---+---+---+---+-----+ 
|a |y |n |n |y | 
+---+---+---+---+-----+ 
|b |n |y |n |n | 
+---+---+---+---+-----+ 
|c |n |n |y |n | 
+---+---+---+---+-----+ 
|d |n |y |y |n | 
+---+---+---+---+-----+ 
|e |y |n |n |n | 
+---+---+---+---+-----+ 

在SSRS报告,我需要显示所有具有所有从给定参数的功能的汽车。这将从报告中接收参数,如:Nav-yes/no,Bth-yes/no,Eco-yes/no,Radio-yes/no。

举例来说,如果参数输入为“是”的导航和“否”别人,结果表应该是这样的;

+---+----------+ 
|Car|Features | 
+---+----------+ 
|a |Nav, Radio| 
+---+----------+ 
|e |Nav  | 
+---+----------+ 

我认为这很简单,但是当我尝试完成查询时,这有点让我发疯。以下是我认为最初会让我得到我需要的东西,但没有。

select Car, 
case when @nav = 'y' then 'Nav ' else '' end + 
case when @bth = 'y' then 'Bth ' else '' end + 
case when @eco = 'y' then 'Eco ' else '' end + 
case when @radio = 'y' then 'Radio ' else '' end As Features 
from CarFeatures 
where (nav = @nav -- here I don't want the row to be picked if the input is 'n' 
or bth = @bth 
or eco = @eco 
or radio = @radio) 

基本逻辑应该是这样的,如果没有为每个参数是一排“是”,列出了我所有特性,“是”该行,即使参数是“不”为那些其他功能。

此外,我不考虑过滤报告。我希望这是存储过程本身。

我当然希望避免考虑我有4个参数和4中,如果可能不是一个更好的事情做多排列IFS。

谢谢。

+0

你可以使用'如果-else'逻辑存储过程 – Milen

+0

你可以声明@SQL为nvarchar(最大),建立一个查询字符串,你想和EXEC( @SQL)放到临时表中,或者回到调用者。您还可以查看FOR XML的用法。通过这种方式,您可以将汽车功能连接成一列,而另一辆车连接到另一辆车。 – Pierre

+0

这是针对非规格化数据的问题之一。 – Jodrell

回答

0

--Aha!我有点想通了(非常高兴):)。由于列的值只能是'y'或'n',因此在参数值为no时忽略,我只会要求它查找永远不会存在的值。 - 如果任何人有更好的方式来做或增强我的(首选)将不胜感激。 - 感谢所有回复的人。既然这是已经存在的表的一部分,也是一个大的存储过程,我不愿意回答以前的问题。这里

--variable声明和分配

select Car, 
case when @nav = 'y' then 'Nav ' else '' end + 
case when @bth = 'y' then 'Bth ' else '' end + 
case when @eco = 'y' then 'Eco ' else '' end + 
case when @radio = 'y' then 'Radio ' else '' end As Features 
from CarFeatures 
where (nav = (case when @nav = 'y' then 'Y' else 'B' end 
       OR case when @bth = 'y' then 'Y' else 'B' end 
       OR case when @eco = 'y' then 'Y' else 'B' end 
       OR case when @radio = 'y' then 'Y' else 'B' end 
    ) 
2

你的架构是笨拙和去归一化,就应该有3个表,

Car 

Feature 

CarFeature 

CarFeature表应包括两列,CarIdFeatureId的。然后你可以不喜欢,

SELECT DISTINCT 
      cr.CarId 
    FROM 
      CarFeature cr 
    WHERE 
      cr.FeatureId IN SelectedFeatures; 

咆哮 {

它不仅会很容易地添加功能,而无需更改架构, 提供更好的性能,因为支持基于组操作 覆盖良好的indecies,整体使用更少的存储,因为你没有 不再需要存储No值,你要遵守一些知名 深思熟虑,并建立模式通过40多年的 支持发展努力和澄清。

}


如果出于某种原因,你不能改变的数据或模式,可以UNPIVOT这样的列,Fiddle Here

SELECT 
     p.Car, 
     p.Feature 
    FROM 
     (
     SELECT 
      Car, 
      Nav, 
      Bth, 
      Eco, 
      Radio 
     FROM 
      CarFeatures) cf 
    UNPIVOT (Value For Feature In (Nav, Bth, Eco, Radio)) p 
    WHERE 
     p.Value='Y'; 

或者,你可以这样做像这样的旧款式Fiddle Here

SELECT 
     Car, 
     'Nav' Feature 
    FROM 
     CarFeatures 
    WHERE 
     Nav = 'Y' 
UNION ALL 
SELECT 
     Car, 
     'Bth' Feature 
    FROM 
     CarFeatures 
    WHERE 
    Bth = 'Y' 
UNION ALL 
SELECT 
     Car, 
     'Eco' Feature 
    FROM 
     CarFeatures 
    WHERE 
     Eco = 'Y' 
UNION ALL 
SELECT 
     Car, 
     'Radio' Feature 
    FROM 
     CarFeatures 
    WHERE 
    Radio = 'Y' 

本质上,denormalise到子查询。这两个查询得出的结果是这样,

CAR FEATURE 
A  Nav 
A  Radio 
B  Bth 
B  Radio 
C  Eco 
D  Bth 
D  Eco 
E  Nav 
+0

@jordell - 你很可能是对的,我同意你的说法。但是,这是一个现有的表格,并且在这一点上正常化,因为这种情况对于我来说至少会超出范围。我可能不得不考虑是否有其他情况,在我看来,有太多情况需要考虑。 – NoSaidTheCompiler

0

试试这个它的工作...........

declare @table table (Car char(1),Nav char(1),Bth char(1),Eco char(1),Radio char(1)) 
insert into @table 
select 'a', 'y' , 'n' , 'n', 'y' 
union all 
select 'b', 'n' , 'y' , 'n', 'n' 
union all 
select 'c', 'n' , 'n' , 'y', 'n' 
union all 
select 'd', 'n' , 'y' , 'y', 'n' 
union all 
select 'e', 'y' , 'n' , 'n', 'n' 

select * from @table 


select a.car, 
Nav = left((case when a.nav = 'y' then 'Nav, ' else '' end) + 
(case when a.bth = 'y' then 'Bth, ' else '' end)+ 
(case when a.Eco = 'y' then 'Eco, ' else '' end)+ 
(case when a.Radio = 'y' then 'Radio,' else '' end), 
(len(((case when a.nav = 'y' then 'Nav, ' else '' end) + 
(case when a.bth = 'y' then 'Bth, ' else '' end)+ 
(case when a.Eco = 'y' then 'Eco, ' else '' end)+ 
(case when a.Radio = 'y' then 'Radio,' else '' end)))-1)) 
from @table a 
1
Try This, I believe this will solve your purpose.. 

SELECT Car, 
    tblPivot.Property AS Features, 
    tblPivot.Value 
    INTO #tmpFeature 
FROM  
(SELECT CONVERT(sql_variant,Car) AS Car,CONVERT(sql_variant,NAV) AS NAV,   CONVERT(sql_variant,BTH) AS BTH,  CONVERT(sql_variant,ECO) AS ECO, 
CONVERT(sql_variant,Radio) AS Radio FROM CarFeatures) CarFeatures 
UNPIVOT (Value For Property In (NAV,BTH, ECO, Radio)) as tblPivot 
Where tblPivot.Value='y' 


SELECT 
    Car, 
    STUFF((
    SELECT ', ' + Features 
    FROM #tmpFeature 
    WHERE (Car = Results.Car) 
    FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)') 
    ,1,2,'') AS Features 
FROM #tmpFeature Results 
GROUP BY Car