Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.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
Mysql 列到行查询_Mysql_Select_Pivot - Fatal编程技术网

Mysql 列到行查询

Mysql 列到行查询,mysql,select,pivot,Mysql,Select,Pivot,我有一张这样的桌子: Company Year Revenue Cost Profit ABC 1 10 6 4 ABC 2 12 7 5 ABC 3 14 8 6 XYZ 1 25 18 7 XYZ 2 27 19 8 XYZ 3 2

我有一张这样的桌子:

Company Year    Revenue Cost    Profit
ABC      1         10    6        4
ABC      2         12    7        5
ABC      3         14    8        6
XYZ      1         25   18        7
XYZ      2         27   19        8
XYZ      3         29   20        9
Company Item    1   2   3
ABC     Revenue 10  12  14
ABC     Cost    6   7   8
ABC     Profit  4   5   6
XYZ     Revenue 25  27  29
XYZ     Cost    18  19  20
XYZ     Profit  7   8   9
我希望它看起来像这样:

Company Year    Revenue Cost    Profit
ABC      1         10    6        4
ABC      2         12    7        5
ABC      3         14    8        6
XYZ      1         25   18        7
XYZ      2         27   19        8
XYZ      3         29   20        9
Company Item    1   2   3
ABC     Revenue 10  12  14
ABC     Cost    6   7   8
ABC     Profit  4   5   6
XYZ     Revenue 25  27  29
XYZ     Cost    18  19  20
XYZ     Profit  7   8   9
交叉表查询只允许一个值。我可以使用单独的交叉表查询收入、成本和利润,并使用Union函数进行合并,但必须有一种更简单的方法

任何帮助都将不胜感激

Max

试试这个:

SELECT Company, Item, Col1 AS 1, Col2 AS 2, Col3 AS 3
FROM (SELECT a.Company, 'Revenue' AS Item, MAX(IF(a.Year = 1, a.Revenue, 0)) AS Col1, 
             MAX(IF(a.Year = 2, a.Revenue, 0)) AS Col2, MAX(IF(a.Year = 3, a.Revenue, 0)) AS Col3
      FROM tableA a 
      GROUP BY a.Company 
      UNION 
      SELECT a.Company, 'Cost' AS Item, MAX(IF(a.Year = 1, a.Cost, 0)) AS Col1, 
             MAX(IF(a.Year = 2, a.Cost, 0)) AS Col2, MAX(IF(a.Year = 3, a.Cost, 0)) AS Col3
      FROM tableA a 
      GROUP BY a.Company 
      UNION
      SELECT a.Company, 'Profit' AS Item, MAX(IF(a.Year = 1, a.Profit, 0)) AS Col1, 
             MAX(IF(a.Year = 2, a.Profit, 0)) AS Col2, MAX(IF(a.Year = 3, a.Profit, 0)) AS Col3
      FROM tableA a 
      GROUP BY a.Company 
     ) AS A 
ORDER BY Company, FIELD(Item, 'Revenue', 'Cost', 'Profit')
试试这个:

SELECT Company, Item, Col1 AS 1, Col2 AS 2, Col3 AS 3
FROM (SELECT a.Company, 'Revenue' AS Item, MAX(IF(a.Year = 1, a.Revenue, 0)) AS Col1, 
             MAX(IF(a.Year = 2, a.Revenue, 0)) AS Col2, MAX(IF(a.Year = 3, a.Revenue, 0)) AS Col3
      FROM tableA a 
      GROUP BY a.Company 
      UNION 
      SELECT a.Company, 'Cost' AS Item, MAX(IF(a.Year = 1, a.Cost, 0)) AS Col1, 
             MAX(IF(a.Year = 2, a.Cost, 0)) AS Col2, MAX(IF(a.Year = 3, a.Cost, 0)) AS Col3
      FROM tableA a 
      GROUP BY a.Company 
      UNION
      SELECT a.Company, 'Profit' AS Item, MAX(IF(a.Year = 1, a.Profit, 0)) AS Col1, 
             MAX(IF(a.Year = 2, a.Profit, 0)) AS Col2, MAX(IF(a.Year = 3, a.Profit, 0)) AS Col3
      FROM tableA a 
      GROUP BY a.Company 
     ) AS A 
ORDER BY Company, FIELD(Item, 'Revenue', 'Cost', 'Profit')

你可以试试

SELECT Company, 
    item, 
    SUBSTRING_INDEX(SUBSTRING_INDEX(item_details, ',', 1), ',', -1) AS `1`,
    SUBSTRING_INDEX(SUBSTRING_INDEX(item_details, ',', 2), ',', -1) AS `2`,
    SUBSTRING_INDEX(SUBSTRING_INDEX(item_details, ',', 3), ',', -1) AS `3`
FROM
(
    SELECT Company, 'Revenue' AS item, GROUP_CONCAT(Revenue ORDER BY `Year`) AS item_details
    FROM SomeTable
    GROUP BY Company
    UNION
    SELECT Company, 'Cost' AS item, GROUP_CONCAT(Cost ORDER BY `Year`)
    FROM SomeTable
    GROUP BY Company
    UNION
    SELECT Company, 'Profit' AS item, GROUP_CONCAT(Profit ORDER BY `Year`)
    FROM SomeTable
    GROUP BY Company
) Sub1
ORDER BY Company, FIELD(Item, 'Revenue', 'Cost', 'Profit')
SQL fiddle为您提供:-


你可以试试

SELECT Company, 
    item, 
    SUBSTRING_INDEX(SUBSTRING_INDEX(item_details, ',', 1), ',', -1) AS `1`,
    SUBSTRING_INDEX(SUBSTRING_INDEX(item_details, ',', 2), ',', -1) AS `2`,
    SUBSTRING_INDEX(SUBSTRING_INDEX(item_details, ',', 3), ',', -1) AS `3`
FROM
(
    SELECT Company, 'Revenue' AS item, GROUP_CONCAT(Revenue ORDER BY `Year`) AS item_details
    FROM SomeTable
    GROUP BY Company
    UNION
    SELECT Company, 'Cost' AS item, GROUP_CONCAT(Cost ORDER BY `Year`)
    FROM SomeTable
    GROUP BY Company
    UNION
    SELECT Company, 'Profit' AS item, GROUP_CONCAT(Profit ORDER BY `Year`)
    FROM SomeTable
    GROUP BY Company
) Sub1
ORDER BY Company, FIELD(Item, 'Revenue', 'Cost', 'Profit')
SQL fiddle为您提供:-


第二种方法。没有测试,所以可能有一些拼写错误,但是执行一些SQL来获取数据,然后围绕细节循环,将它们转发到一个对象以输出行。这将处理任何公司一年内丢失数据的情况

请注意,如果您有一个感兴趣的年份表和一个公司表,那么可以大大简化SQL

<?php

$sql = "SELECT Sub1.Year, Sub2.Company, IFNULL(SomeTable.Revenue, 0) AS aValue, 'Revenue' AS Item
        FROM
        (
            SELECT DISTINCT Year FROM SomeTable
        ) Sub1
        CROSS JOIN 
        (
            SELECT DISTINCT Company FROM SomeTable
        ) Sub2
        LEFT OUTER JOIN SomeTable
        ON Sub1.Year = SomeTable.Year
        AND Sub2.Company = SomeTable.Company
        UNION
        SELECT Sub1.Year, Sub2.Company, IFNULL(SomeTable.Cost, 0) AS aValue, 'Cost' AS Item
        FROM
        (
            SELECT DISTINCT Year FROM SomeTable
        ) Sub1
        CROSS JOIN 
        (
            SELECT DISTINCT Company FROM SomeTable
        ) Sub2
        LEFT OUTER JOIN SomeTable
        ON Sub1.Year = SomeTable.Year
        AND Sub2.Company = SomeTable.Company
        UNION
        SELECT Sub1.Year, Sub2.Company, IFNULL(SomeTable.Profit, 0) AS aValue, 'Profit' AS Item
        FROM
        (
            SELECT DISTINCT Year FROM SomeTable
        ) Sub1
        CROSS JOIN 
        (
            SELECT DISTINCT Company FROM SomeTable
        ) Sub2
        LEFT OUTER JOIN SomeTable
        ON Sub1.Year = SomeTable.Year
        AND Sub2.Company = SomeTable.Company
        ORDER BY Company, FIELD(Item, 'Revenue', 'Cost', 'Profit'), Year";

$query = $db->query($sql) or die($db->error()) ;
if ($row = $this->db->fetchAssoc())
{
    echo "<table>";
    $PrevCompany = $row['Company'];
    $PrevItem = $row['Item'];
    $aLine = new ProcessLine($PrevCompany, $PrevItem, true);
    do
    {
        if ($PrevCompany != $row['Company'] or $PrevItem != $row['Item'])
        {
            unset($aLine);
            $PrevCompany = $row['Company'];
            $PrevItem = $row['Item'];
            $aLine = new ProcessLine($PrevCompany, $PrevItem);
        }
        $aLine->Assign_Detail($row['Year'], $row['aValue'])

    } while($row = $this->db->fetchAssoc());
    unset($aLine);
    echo "</table>";
}

class ProcessLine
{
    private $Company;
    private $Item;
    private $row_details = array();
    private $FirstRow = false
    public __CONSTRUCT($Company, $Item, $FirstRow=false)
    {
        $this->Company = $Company;
        $this->Item = $Item;
    }

    public __DESTRUCT()
    {
        if ($this->Firstrow)
        {
            echo "<tr><th>".$this->Company."</th><th>".$this->Item."</th>";
            foreach($row_details AS $row_year=>$row_value)
            {
                echo "<th>$row_year</th>";
            }
            echo "</tr>";
        }
        echo "<tr><td>".$this->Company."</td><td>".$this->Item."</td><td>".implode("</td><td>", $row_details)."</td></tr>";
    }

    public Assign_Detail($in_year, $in_value)
    {
        $row_details[$in_year] = $in_value;
    }
}

?>

第二种方法。没有测试,所以可能有一些拼写错误,但是执行一些SQL来获取数据,然后围绕细节循环,将它们转发到一个对象以输出行。这将处理任何公司一年内丢失数据的情况

请注意,如果您有一个感兴趣的年份表和一个公司表,那么可以大大简化SQL

<?php

$sql = "SELECT Sub1.Year, Sub2.Company, IFNULL(SomeTable.Revenue, 0) AS aValue, 'Revenue' AS Item
        FROM
        (
            SELECT DISTINCT Year FROM SomeTable
        ) Sub1
        CROSS JOIN 
        (
            SELECT DISTINCT Company FROM SomeTable
        ) Sub2
        LEFT OUTER JOIN SomeTable
        ON Sub1.Year = SomeTable.Year
        AND Sub2.Company = SomeTable.Company
        UNION
        SELECT Sub1.Year, Sub2.Company, IFNULL(SomeTable.Cost, 0) AS aValue, 'Cost' AS Item
        FROM
        (
            SELECT DISTINCT Year FROM SomeTable
        ) Sub1
        CROSS JOIN 
        (
            SELECT DISTINCT Company FROM SomeTable
        ) Sub2
        LEFT OUTER JOIN SomeTable
        ON Sub1.Year = SomeTable.Year
        AND Sub2.Company = SomeTable.Company
        UNION
        SELECT Sub1.Year, Sub2.Company, IFNULL(SomeTable.Profit, 0) AS aValue, 'Profit' AS Item
        FROM
        (
            SELECT DISTINCT Year FROM SomeTable
        ) Sub1
        CROSS JOIN 
        (
            SELECT DISTINCT Company FROM SomeTable
        ) Sub2
        LEFT OUTER JOIN SomeTable
        ON Sub1.Year = SomeTable.Year
        AND Sub2.Company = SomeTable.Company
        ORDER BY Company, FIELD(Item, 'Revenue', 'Cost', 'Profit'), Year";

$query = $db->query($sql) or die($db->error()) ;
if ($row = $this->db->fetchAssoc())
{
    echo "<table>";
    $PrevCompany = $row['Company'];
    $PrevItem = $row['Item'];
    $aLine = new ProcessLine($PrevCompany, $PrevItem, true);
    do
    {
        if ($PrevCompany != $row['Company'] or $PrevItem != $row['Item'])
        {
            unset($aLine);
            $PrevCompany = $row['Company'];
            $PrevItem = $row['Item'];
            $aLine = new ProcessLine($PrevCompany, $PrevItem);
        }
        $aLine->Assign_Detail($row['Year'], $row['aValue'])

    } while($row = $this->db->fetchAssoc());
    unset($aLine);
    echo "</table>";
}

class ProcessLine
{
    private $Company;
    private $Item;
    private $row_details = array();
    private $FirstRow = false
    public __CONSTRUCT($Company, $Item, $FirstRow=false)
    {
        $this->Company = $Company;
        $this->Item = $Item;
    }

    public __DESTRUCT()
    {
        if ($this->Firstrow)
        {
            echo "<tr><th>".$this->Company."</th><th>".$this->Item."</th>";
            foreach($row_details AS $row_year=>$row_value)
            {
                echo "<th>$row_year</th>";
            }
            echo "</tr>";
        }
        echo "<tr><td>".$this->Company."</td><td>".$this->Item."</td><td>".implode("</td><td>", $row_details)."</td></tr>";
    }

    public Assign_Detail($in_year, $in_value)
    {
        $row_details[$in_year] = $in_value;
    }
}

?>

出于可伸缩性和灵活性的原因,此类问题最好留给应用程序级代码解决,例如,在有序的结果集上进行简单的PHP循环,但只是为了好玩

SELECT company
     , item
     , MAX(CASE WHEN year = 1 THEN value END) y1
     , MAX(CASE WHEN year = 2 THEN value END) y2
     , MAX(CASE WHEN year = 3 THEN value END) y3
  FROM 
     ( SELECT company, year, 'revenue' item, revenue value FROM my_table
       UNION
       SELECT company, year, 'cost',cost FROM my_table
       UNION
       SELECT company, year, 'profit',profit FROM my_table
     ) x
 GROUP
    BY company
     , item
 ORDER 
    BY company
     , FIELD(item,'Revenue','Cost','Profit');

出于可伸缩性和灵活性的原因,此类问题最好留给应用程序级代码解决,例如,在有序的结果集上进行简单的PHP循环,但只是为了好玩

SELECT company
     , item
     , MAX(CASE WHEN year = 1 THEN value END) y1
     , MAX(CASE WHEN year = 2 THEN value END) y2
     , MAX(CASE WHEN year = 3 THEN value END) y3
  FROM 
     ( SELECT company, year, 'revenue' item, revenue value FROM my_table
       UNION
       SELECT company, year, 'cost',cost FROM my_table
       UNION
       SELECT company, year, 'profit',profit FROM my_table
     ) x
 GROUP
    BY company
     , item
 ORDER 
    BY company
     , FIELD(item,'Revenue','Cost','Profit');


如果一家公司的收入、成本和利润超过10行呢?这很有可能。。每家公司将有20排。其他项目将是管理费用、营销等。如何改变表格结构,而不是一对多关系?通常,最好在表示层/应用程序级代码中处理数据显示问题,例如,有序阵列上的一个简单PHP循环。上述数据来自一个查询,因此一对多关系不适用于苹果。如果一家公司的收入、成本和利润超过10行,该怎么办?这很可能。。每家公司将有20排。其他项目将是管理费用、营销等。如何改变表格结构,而不是一对多关系?通常,最好在表示层/应用程序级代码中处理数据显示问题,例如,有序数组上的一个简单PHP循环。上述数据来自一个查询,因此一对多关系不适用。太好了!在调整IF和field语句后工作正常。还有一个问题——我有20年的数据。有没有一种更简单的方法来写MAX语句?太棒了!在调整IF和field语句后工作正常。还有一个问题——我有20年的数据。是否有一种更简单的方法来编写MAX statementKickstart,就像您优雅的解决方案一样,但请耐心等待这位新手。将代码粘贴到我的查询中并更改为我的表名。Get error syntax查询表达式“GROUP_CONCATRevenue ORDER BY Year”中缺少运算符时出错。我看不到任何明显的东西。你能粘贴完整的查询吗?可能错误在查询的其他地方。正如sqlfiddle显示的那样,它应该按原样工作。选择公司作为Expr1,项目作为Expr2,子字符串作为Expr2,子字符串作为1,子字符串作为1,子字符串作为1,子字符串作为Expr1,子字符串作为Expr1,子字符串作为EXTRING,子字符串作为Expr2,子字符串作为Expr2,子字符串作为EXTRING,子字符串作为3,子字符串作为3,子字符串作为选择公司的“收入”项目,根据项目详细信息按年度分组合同订单从表A按公司分组工会选择公司,“成本”作为项目,按年度分组合同成本订单从表A按公司分组工会选择公司,“利润”作为项目,按年度分组合同利润订单从表A按公司分组工会选择公司子订单,字段项、‘收入’、‘成本’、‘利润’;我刚才提到的1、2和3年的列名。然而,对于要成为列名的列名,它们需要在其周围加上背景标记。如果没有back tics,您将得到一个错误,但是有了它们,SQL似乎可以工作。将SQL FIDLE更新为test-Kickstart,就像您优雅的解决方案一样,但请容忍这个新手。将代码粘贴到我的查询中并更改为我的表名。Get error syntax查询表达式“GROUP_CONCATRevenue ORDER BY Year”中缺少运算符时出错。我看不到任何明显的东西。你能粘贴完整的查询吗?可能错误在查询的其他地方。正如sqlfiddle显示的那样,它应该按原样工作。选择公司作为Expr1,项目作为Expr2,子字符串作为Expr2,子字符串作为1,子字符串作为1,子字符串作为1,子字符串作为Expr1,子字符串作为Expr1,子字符串作为EXTRING,子字符串作为Expr2,子字符串作为Expr2,子字符串作为EXTRING,子字符串作为3,子字符串作为3,子字符串作为选择公司的“收入”项目,集团公司按年度将订单列为项目详细信息从表A集团公司工会选择“成本”列为项目,集团公司成本O