【问题标题】:Crosstab 2 conditions in SQL Server 2008SQL Server 2008 中的交叉表 2 条件
【发布时间】:2018-04-21 15:00:05
【问题描述】:

我需要这方面的帮助。

我需要使视图大小与颜色交叉以获得项目平衡

我尝试了常规交叉表,但我做不到。

我有这张桌子:

ItemCode    ItemName     Size    Color   Balance
--------------------------------------------------
1           Shirt         S      White      10
1           Shirt         M      White      10
1           Shirt         L      White      10
1           Shirt         S      Black      10
1           Shirt         M      Black      10
1           Shirt         L      Black      10

我需要知道如何使用交叉表查询将这个表变成这个结果:

ItemCode    Item Name   Colors     S     M     L
--------------------------------------------------
1           Shirt        White     10    10    10
1           Shirt        Black     10    10    10

有人可以帮忙吗?

【问题讨论】:

  • 它是否总是只有 S、M 或 L,或者在您可能需要动态枢轴的地方可能还有更多?
  • crosstab 是一个特定的 MS Access 查询,没有其他 RDMBS 共享。您的 SQL Server 是否连接到 MS Access 前端?

标签: sql-server crosstab


【解决方案1】:

不确定您尝试了什么,但假设您不需要动态列,一个基本的交叉表(也称为条件聚合)将产生这些结果。

select ItemCode
    , ItemName
    , Color
    , S = MAX(CASE when Size = 'S' then Balance end)
    , M = MAX(CASE when Size = 'M' then Balance end)
    , L = MAX(CASE when Size = 'L' then Balance end)
from SomeTable
group by ItemCode
    , ItemName
    , Color

--编辑--

您可以使用动态交叉表来解决此问题。我从 Jeff Moden 和他的文章这里学到了这项技术。 http://www.sqlservercentral.com/articles/Crosstab/65048/

这是一个完整的工作示例,所以这里也有很多设置。

if OBJECT_ID('tempdb..#Something') is not null
    drop table #Something

create table #Something
(
    ItemCode int
    , ItemName varchar(10)
    , Size char(1)
    , Color varchar(10)
    , Balance int
)

insert #Something values
(1, 'Shirt', 'S', 'White', 10)
, (1, 'Shirt', 'M', 'White', 10)
, (1, 'Shirt', 'L', 'White', 10)
, (1, 'Shirt', 'S', 'Black', 10)
, (1, 'Shirt', 'M', 'Black', 10)
, (1, 'Shirt', 'L', 'Black', 10)

declare @StaticPortion nvarchar(2000) = 
    'with OrderedResults as
    (
        SELECT s.ItemCode
            , s.ItemName
            , s.Color
            , s.Size
            , s.Balance
            , ROW_NUMBER() over(partition by s.ItemCode, s.ItemName, s.Color order by s.Size desc) as RowNum
        FROM #Something s
    )
    select ItemCode
        , ItemName
        , Color';

declare @DynamicPortion nvarchar(max) = '';
declare @FinalStaticPortion nvarchar(2000) = ' from OrderedResults Group by ItemCode
        , ItemName
        , Color 
        order by ItemCode
        , ItemName
        , Color';

--the following cte is a tally table (another trick I learned from Jeff Moden)
with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
cteTally(N) AS 
(
    SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E2
)

select @DynamicPortion = @DynamicPortion + 
', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then Balance end) as ' + sizes.SizeName + CHAR(10)
from cteTally t
join 
(
    values
    ('S', 1)
    ,('M', 2)
    ,('L', 3)
) sizes(SizeName, SizeNum) on sizes.SizeNum = t.N --This would be better if you have a table of sizes you can join to
where t.N <= 
(
    select top 1 Count(s.Size)
    FROM #Something s 
    group by s.ItemCode
        , s.ItemName
        , s.Color
    order by COUNT(*) desc
)


declare @SqlToExecute nvarchar(max) = @StaticPortion + @DynamicPortion + @FinalStaticPortion;

--you can comment the following. it is here for now so you can view the dynamic sql before it executes
select @SqlToExecute

--Once you are satisfied that the dynamic sql generated is correct simply uncomment the below line
--exec sp_executesql @SqlToExecute

【讨论】:

  • 很好,但我使用的是未绑定的尺寸而不是 s-m-l,我只能这样做吗??
  • 所以你需要它是完全动态的吗?只是试图了解问题的范围不是问题。
  • @MAXSoft 参见上面的编辑。这现在包括一个完全动态的示例。哦....刚刚意识到这里的输出不是你想要的。给我一点,我会调整它。
  • 好的,现在应该会产生你想要的输出。
猜你喜欢
  • 2014-04-01
  • 2012-06-22
  • 2012-02-28
  • 1970-01-01
  • 1970-01-01
  • 2017-06-15
  • 1970-01-01
  • 1970-01-01
  • 2013-01-25
相关资源
最近更新 更多