Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL查询-将表的行转换为列_Sql - Fatal编程技术网

SQL查询-将表的行转换为列

SQL查询-将表的行转换为列,sql,Sql,我有一个奇怪的SQL问题 我有两个表,比如products(带列pid和pname)和rules(带列rid和rname),这两个表没有任何共同之处。产品表有100行,规则表有16行 我需要以这样一种方式编写查询:我得到的结果的第一列是pname,其余的列是表规则的16行。换句话说,我需要转换结果列中的表规则行。所以,在结果中,我应该能够有100行(产品表中的所有pname)和17列(规则表中的pname和16行) 你能帮我写一个这样的问题吗?我尝试使用case语句将行转换为列,但是当与乘积表的

我有一个奇怪的SQL问题

我有两个表,比如products(带列pid和pname)和rules(带列rid和rname),这两个表没有任何共同之处。产品表有100行,规则表有16行

我需要以这样一种方式编写查询:我得到的结果的第一列是pname,其余的列是表规则的16行。换句话说,我需要转换结果列中的表规则行。所以,在结果中,我应该能够有100行(产品表中的所有pname)和17列(规则表中的pname和16行)


你能帮我写一个这样的问题吗?我尝试使用case语句将行转换为列,但是当与乘积表的结果结合时,我得到的行数是乘积表和规则表的笛卡尔乘积,这是我不想要的。我希望行数等于product表中的行数,列数等于rule表中的行数。您可以提供帮助吗?

如果您使用的是SQL Server 2005+,您可以使用Pivot和Unpivot命令将行转换为列,将列转换为行。

如果您使用的是SQL Server 2005+,您可以使用Pivot和Unpivot命令将行转换为列,将列转换为行。

这称为。要获得动态的列数,您可能必须使用动态SQL—从另一个查询动态创建查询,并使用任何可用的eval方法。根据您使用的语言,调用代码可能很容易处理这一问题。我建议用另一种方式进行重构,或者准备好几个小时的学习。如果没有更多信息,我真的无法帮助您进行查询—数据库模式,以及您使用的sql db

这里有一个相当复杂的例子,尽管我不确定它会有多大帮助

ALTER PROCEDURE [dbo].[CMS_GetCollection]
    @sectionContentTemplateID int
    ,@count int = null
AS
BEGIN
    SET NOCOUNT ON;
SET NOCOUNT ON;

    declare @columns varchar(max)
    select 
        @columns = COALESCE(@columns + ',[' + cte.name + '/' + a.name + ']', '[' + cte.name + '/' + a.name + ']')
    from tcmssection_contenttemplate sct 
                inner join tcmssection s on s.sectionid = sct.sectionid
                inner join tcmscontenttemplate ct on ct.contenttemplateid = sct.contenttemplateid
                inner join tcmscontenttemplate_element cte on cte.contenttemplateid = ct.contenttemplateid
                inner join tcmselement e on cte.elementid = e.elementid
                inner join tcmsattribute a on e.elementid = a.elementid 
    where 
        a.isadmin = 0
        and sct.sectioncontenttemplateid = @sectionContentTemplateID

    declare @query varchar(max)
    set @query = 
    'select ' + case when @count is not null then 
    ' top ' + convert(varchar(10),@count) else '' end + '
        [url]
        ,pageId,pageName,sortOrder
        ,[date]
        , ' + @columns + '
    from (
        select 
            s.domainpath + p.filename as [url]
            ,cte.name + ''/'' + a.name as [element.attribute]
            ,isnull(pva.valuevarchar, isnull(pva.valuetext,'''')) as [value]
            ,pv.datepublished as [date],isnull(p.sortOrder,0) as sortOrder,p.pageID,p.name as pageName
          from tcmssection_contenttemplate sct 
            inner join tcmssection s on s.sectionid = sct.sectionid
            inner join tcmspage p on p.sectioncontenttemplateid = sct.sectioncontenttemplateid
            inner join tcmscontenttemplate ct on ct.contenttemplateid = sct.contenttemplateid
            inner join tcmscontenttemplate_element cte on cte.contenttemplateid = ct.contenttemplateid
            inner join tcmselement e on cte.elementid = e.elementid
            inner join tCMSPageVersion pv on p.pageID = pv.pageID
                and pv.pageVersionID = (
                    select top 1 pageVersionID 
                    from tCMSPageVersion 
                    where pageID = p.pageID and datePublished is not null and datecancelled is null 
                    order by datePublished desc
                )
            inner join tcmsattribute a on e.elementid = a.elementid
            left outer join tcmspageversion_element pve on pve.pageversionid = pv.pageversionid 
                and pve.elementid = e.elementid and pve.name = cte.name
            left outer join tcmspageversion_attribute pva on pva.attributeid = a.attributeid 
                and pve.pageversionelementid = pva.pageversionelementid
        where 
            p.isDeleted = 0
            and a.isadmin = 0
            and sct.sectioncontenttemplateid = ' + convert(varchar(10), @sectionContentTemplateID) + '

    ) [data]
    pivot (
        max([value])
        for [element.attribute] 
        in ( ' + @columns +  ' )
    ) as [pivot]    
    order by [date] desc'

    execute(@query)

END
这被称为一个。要获得动态的列数,您可能必须使用动态SQL—从另一个查询动态创建查询,并使用任何可用的eval方法。根据您使用的语言,调用代码可能很容易处理这一问题。我建议用另一种方式进行重构,或者准备好几个小时的学习。如果没有更多信息,我真的无法帮助您进行查询—数据库模式,以及您使用的sql db

这里有一个相当复杂的例子,尽管我不确定它会有多大帮助

ALTER PROCEDURE [dbo].[CMS_GetCollection]
    @sectionContentTemplateID int
    ,@count int = null
AS
BEGIN
    SET NOCOUNT ON;
SET NOCOUNT ON;

    declare @columns varchar(max)
    select 
        @columns = COALESCE(@columns + ',[' + cte.name + '/' + a.name + ']', '[' + cte.name + '/' + a.name + ']')
    from tcmssection_contenttemplate sct 
                inner join tcmssection s on s.sectionid = sct.sectionid
                inner join tcmscontenttemplate ct on ct.contenttemplateid = sct.contenttemplateid
                inner join tcmscontenttemplate_element cte on cte.contenttemplateid = ct.contenttemplateid
                inner join tcmselement e on cte.elementid = e.elementid
                inner join tcmsattribute a on e.elementid = a.elementid 
    where 
        a.isadmin = 0
        and sct.sectioncontenttemplateid = @sectionContentTemplateID

    declare @query varchar(max)
    set @query = 
    'select ' + case when @count is not null then 
    ' top ' + convert(varchar(10),@count) else '' end + '
        [url]
        ,pageId,pageName,sortOrder
        ,[date]
        , ' + @columns + '
    from (
        select 
            s.domainpath + p.filename as [url]
            ,cte.name + ''/'' + a.name as [element.attribute]
            ,isnull(pva.valuevarchar, isnull(pva.valuetext,'''')) as [value]
            ,pv.datepublished as [date],isnull(p.sortOrder,0) as sortOrder,p.pageID,p.name as pageName
          from tcmssection_contenttemplate sct 
            inner join tcmssection s on s.sectionid = sct.sectionid
            inner join tcmspage p on p.sectioncontenttemplateid = sct.sectioncontenttemplateid
            inner join tcmscontenttemplate ct on ct.contenttemplateid = sct.contenttemplateid
            inner join tcmscontenttemplate_element cte on cte.contenttemplateid = ct.contenttemplateid
            inner join tcmselement e on cte.elementid = e.elementid
            inner join tCMSPageVersion pv on p.pageID = pv.pageID
                and pv.pageVersionID = (
                    select top 1 pageVersionID 
                    from tCMSPageVersion 
                    where pageID = p.pageID and datePublished is not null and datecancelled is null 
                    order by datePublished desc
                )
            inner join tcmsattribute a on e.elementid = a.elementid
            left outer join tcmspageversion_element pve on pve.pageversionid = pv.pageversionid 
                and pve.elementid = e.elementid and pve.name = cte.name
            left outer join tcmspageversion_attribute pva on pva.attributeid = a.attributeid 
                and pve.pageversionelementid = pva.pageversionelementid
        where 
            p.isDeleted = 0
            and a.isadmin = 0
            and sct.sectioncontenttemplateid = ' + convert(varchar(10), @sectionContentTemplateID) + '

    ) [data]
    pivot (
        max([value])
        for [element.attribute] 
        in ( ' + @columns +  ' )
    ) as [pivot]    
    order by [date] desc'

    execute(@query)

END

老实说,我前阵子因为内部数据处理问题(SQL行的最大长度为24000字节左右)不得不处理这个问题。我的解决方案是使用XML数据类型,因为它使您能够以尽可能少的麻烦完成大多数这些随机类型的数据转换。正如其他作者所说,Pivot的问题在于,Pivot依赖于聚合函数才能成功—这是我从来都不想做的。

老实说,我前一段时间不得不处理一个内部数据处理问题(与SQL行的最大长度为24000字节左右有关)。我的解决方案是使用XML数据类型,因为它使您能够以尽可能少的麻烦完成大多数这些随机类型的数据转换。正如其他作者所说,枢轴的问题在于,枢轴依赖于聚合函数才能成功——这是我从未想过要做的事情。

对于一定数量的列来说,这很好。如果所需的列数将发生变化,您还可以使用动态SQL生成类似的内容

SELECT
  products.pname,
  MAX(CASE WHEN rules.rname = 'Rule 0' THEN products.pid * rules.rid) AS pid_r0,
  MAX(CASE WHEN rules.rname = 'Rule 1' THEN products.pid * rules.rid) AS pid_r1,
  MAX(CASE WHEN rules.rname = 'Rule 2 'THEN products.pid * rules.rid) AS pid_r2,
  ...
FROM products
CROSS JOIN rules
GROUP BY products.pname;

对于一定数量的列,这将很好地工作。如果所需的列数将发生变化,您还可以使用动态SQL生成类似的内容

SELECT
  products.pname,
  MAX(CASE WHEN rules.rname = 'Rule 0' THEN products.pid * rules.rid) AS pid_r0,
  MAX(CASE WHEN rules.rname = 'Rule 1' THEN products.pid * rules.rid) AS pid_r1,
  MAX(CASE WHEN rules.rname = 'Rule 2 'THEN products.pid * rules.rid) AS pid_r2,
  ...
FROM products
CROSS JOIN rules
GROUP BY products.pname;

使用哪种数据库服务器?mysql、sql server、oracle?使用哪种数据库服务器?mysql、sql server、oracle?仍然需要解决动态列数问题,但请使用示例进行解释。请我真的需要这个。仍然需要解决动态列数的问题,但是请用一个例子来解释。请我真的需要这个。我试过这个……但它按字母顺序排列了这些字母。另外,我在product表中有100行,但它只显示了86行。我不知道哪里出了毛病。请帮助。您可以随时输入订单,然后按其他内容(如pid)排序。如果您正在丢失记录,我猜您没有唯一的PNAME,在这种情况下,您可以通过将pid添加到组中。我尝试了这个…但它按字母顺序对PNAME进行排序。另外,我在product表中有100行,但它只显示了86行。我不知道哪里出了毛病。请帮助。您可以随时输入订单,然后按其他内容(如pid)排序。如果您正在丢失记录,我猜您没有唯一的PNAME,在这种情况下,您可以通过将pid添加到组中。您可以帮助我使用类似行上的pivot进行示例吗?您可以帮助我使用类似行上的pivot进行示例吗?您可以帮助我进行示例吗?您可以帮助我进行示例吗?