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