我的桌子看起来像这样:
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
交叉表查询仅允许一个值。我可以使用单独的交叉表查询为Revenue,Cost和Profit以及使用Union功能的组合,但必须有一个更简单的方法。
任何帮助都会非常感激。
最高
答案 0 :(得分:2)
您尝试的变化。
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小提琴: -
答案 1 :(得分:1)
试试这个:
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')
答案 2 :(得分:1)
出于可伸缩性(和灵活性)的原因,这样的问题最好留给应用程序级代码(例如,在有序的结果集上的简单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');
答案 3 :(得分:0)
第二种方式。没有经过测试(可能是一些拼写错误),但是做一些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;
}
}
?>