例如,给出了包含这些列的货币汇率表(在这里使用3,但在我的情况下,大约有30个):
date | eur | usd | gbp
2010-01-28 | X | Y | Z
如何将其转换为此版本(使用具有最新日期的行):
currency | rate
eur | X
usd | Y
gbp | Z
我想出了这样的查询:
SELECT 'eur' AS currency, eur AS rate FROM rates WHERE date = (SELECT MAX(date) FROM rates)
UNION
SELECT 'usd' AS currency, usd AS rate FROM rates WHERE date = (SELECT MAX(date) FROM rates)
UNION
...
这是巨大而丑陋的。还有其他解决方案吗?
答案 0 :(得分:5)
有时最简单的解决方案(如果您需要漂亮的查询)是重新设计架构。可能最好的解决方案是将您的表格更改为:
date | currency | rate
-----------+----------+-----
2010-01-28 | eur | X
2010-01-28 | usd | Y
2010-01-28 | gbp | Z
在日期和货币上有适当的索引以表现。这就是应该在3NF中的方式,因为费率相互依赖,违反了3NF规则:
每一栏必须取决于钥匙,整个钥匙以及钥匙,所以请帮助我Codd。
(我喜欢那个小曲子)。另一种方法是提供一个视图,它执行相同的操作,然后查询视图。这对于DBMS而言同样重要,但你的查询至少看起来更漂亮(create view
看起来仍然看起来很丑陋。)
或者您可以接受这样的事实,即某些查询看起来很难看,记录得很好,然后继续: - )
答案 1 :(得分:0)
如果您正在使用MS-SQL,则可以使用UNPIVOT语句:
SELECT
date,
unpiv.ColumnName AS Currency, -- will contain 'eur', 'usd' and so on
unpiv.ColumnValue AS Rate -- will contain the numeric values
FROM
/* your original FROM statement */
Unpivot (ColumnValue FOR ColumnName in (eur, usd /* add more columns here */)) as unpiv
答案 2 :(得分:0)
您是否必须在SQL中执行此操作?
使用编程语言非常简单。
在PHP中:
$q = mysql_query("
SELECT eur, usd, gbp
FROM rates
ORDER BY date DESC
LIMIT 1
");
$table = false;
if($val = mysql_fetch_array($q, MYSQL_ASSOC))
{
$table = array(
'eur' => $val['eur'],
'usd' => $val['usd'],
'gbp' => $val['gbp'],
);
}
echo "currency | rate\n";
echo "-----------------";
foreach($table as $cur => $rate)
echo $curr." | ".$rate."\n";