从articleId匹配的新表中选择具有来自不同表的动态名称的行作为列名

时间:2014-11-12 09:40:33

标签: mysql sql

让我想象一下,我有以下两个表

CREATE TABLE `articles` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `artId` int(11) NOT NULL,
 `price` float NOT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `artId` (`artId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

CREATE TABLE `priceHistory` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `artId` int(11) NOT NULL,
 `price` float NOT NULL,
 `checkdate` datetime NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

以下数据

INSERT INTO `test`.`articles` (`id`, `artId`, `price`) VALUES (NULL, '1', '5'), (NULL, '2', '2'), (NULL, '3', '3'), (NULL, '4', '9.50'), (NULL, '5', '1.3');


INSERT INTO `test`.`priceHistory` (`id`, `artId`, `price`, `checkdate`) VALUES (NULL, '1', '5', '2014-11-10 04:19:56'), (NULL, '1', '8.50', '2014-11-09 04:19:56'), (NULL, '1', '2.5', '2014-11-08 04:19:56'), (NULL, '2', '2', '2014-11-10 04:19:56'), (NULL, '2', '2.5', '2014-11-09 04:19:56'), (NULL, '3', '3', '2014-11-10 04:19:56'), (NULL, '4', '9.50', '2014-11-10 04:19:56'), (NULL, '4', '10', '2014-11-09 04:19:56'), (NULL, '4', '8', '2014-11-08 04:19:56'), (NULL, '4', '7', '2014-11-07 04:19:56'), (NULL, '5', '1.3', '2014-11-10 04:19:56'), (NULL, '5', '2', '2014-11-09 04:19:56');

我现在想做的是以下内容。我想从表articles中选择所有文章,并在同一行中输入每个价格变动/价格历史记录。例如,最终结果应如下所示:

id  articleId   currentPrice    2014-11-07        2014-11-08    2014-11-09      2014-11-10
1   1           5               NULL              2.5               8.5             5
2   2           2               NULL              NULL              2.5             2
3   3           3               NULL              NULL              NULL            3
4   4           9.5             7                 8                 10              9.5
5   5           1.3             NULL              NULL              2               1.3

基本上,我想从另一个表中选择日期并将它们作为列名放入,并相应地填写数据。这有可能用SELECT吗?我找到了关于这个主题的多个资源,但它们要么是固定数量的行,要么让它动态化,因为日期时间可以到达明年(极端的例子),或者它们仅用于一个表。这些是我找到的资源

  1. Problems to select the correct row from a second table
  2. Using MySQL GROUP_CONCAT or PIVOT on multiple joined tables
  3. MySQL - How to display row value as column name using concat and group_concat
  4. Select dynamic Columns in mysql
  5. mysql select dynamic row values as column names, another column as value
  6. Mysql query to dynamically convert rows to columns
  7. MySQL - Rows to Columns
  8. http://buysql.com/mysql/12-how-to-pivot-tables.html

1 个答案:

答案 0 :(得分:3)

那么,你应该付出更多的努力来尝试调整你为你的案例找到的解决方案之一,或者如果你不理解那里的东西 - 努力尝试,询问你不理解的具体事情 - 如何连接两个表,如何连接字符串,如何在MySQL中使用变量等,了解事情是如何工作的。

那就是说,让我们以solution #6为例 - Mysql query to dynamically convert rows to columns,并根据您的情况进行调整。

SET @sql = NULL;

SELECT
  GROUP_CONCAT(
    DISTINCT CONCAT(
      'MAX(IF(CAST(checkdate AS date) = ''', CAST(checkdate AS date), ''', h.price, NULL)) AS ', '`', CAST(checkdate AS date), '`'
    )
    ORDER BY checkdate
  )
INTO
  @sql
FROM
  priceHistory;

SET @sql = CONCAT('
  SELECT
    a.id AS articleId,
    a.price AS currentPrice,
    ', @sql, '
  FROM
    articles a LEFT JOIN priceHistory h
  ON
    a.id = h.artId
  GROUP
    BY a.id
');

PREPARE stmt FROM @sql;

EXECUTE stmt;

Etvoilà!

+-----------+--------------+------------+------------+------------+--------------------+
| articleId | currentPrice | 2014-11-07 | 2014-11-08 | 2014-11-09 | 2014-11-10         |
+-----------+--------------+------------+------------+------------+--------------------+
|         1 |            5 |       NULL |        2.5 |        8.5 |                  5 |
|         2 |            2 |       NULL |       NULL |        2.5 |                  2 |
|         3 |            3 |       NULL |       NULL |       NULL |                  3 |
|         4 |          9.5 |          7 |          8 |         10 |                9.5 |
|         5 |          1.3 |       NULL |       NULL |          2 | 1.2999999523162842 |
+-----------+--------------+------------+------------+------------+--------------------+

您的数据结构中有三件事需要解决。

  1. artId移除articles - 这完全是多余的。
  2. checkdate的类型更改为date
  3. 切勿使用float存储资金(请查看值 1.2999999523162842 ),改为使用NUMERIC
相关问题