-6

我的广告门户有 3 个表,我将 3 个表加入一个查询。

请查看此架构 http://sqlfiddle.com/#!2/8b74b/3

CREATE TABLE `ads` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `ads_title` CHAR(80) NULL DEFAULT NULL,
    PRIMARY KEY (`id`)

);


CREATE TABLE `ads_keys` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `key` CHAR(25) NULL DEFAULT NULL ,
    `inlist` INT(1) UNSIGNED ZEROFILL NULL DEFAULT NULL ,
    PRIMARY KEY (`id`)
);
CREATE TABLE `ads_values` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `ads_id` INT(3) NULL DEFAULT NULL,
    `key_id` INT(10) NULL DEFAULT NULL,
    `value` INT(10) NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `ads_id` (`ads_id`, `key_id`)
);
INSERT INTO `ads` VALUES (1, 'AAA');
INSERT INTO `ads` VALUES (2, 'BBB');
INSERT INTO `ads` VALUES (3, 'CCC');
INSERT INTO `ads` VALUES (4, 'DDD');
INSERT INTO `ads` VALUES (5, 'EEE');
INSERT INTO `ads` VALUES (6, 'FFF');
INSERT INTO `ads_keys` VALUES (1, 'KM', 1);
INSERT INTO `ads_keys` VALUES (2, 'OIL', 0);
INSERT INTO `ads_keys` VALUES (3, 'YEAR', 1);
INSERT INTO `ads_keys` VALUES (4, 'COLOR', 0);
INSERT INTO `ads_keys` VALUES (5, 'SPEED', 0);

INSERT INTO `ads_values` VALUES (1, 1, 1, 89000);
INSERT INTO `ads_values` VALUES (2, 1, 2, 200);
INSERT INTO `ads_values` VALUES (3, 1, 3, 2010);
INSERT INTO `ads_values` VALUES (4, 1, 4, 1);
INSERT INTO `ads_values` VALUES (5, 1, 5, 180);
INSERT INTO `ads_values` VALUES (6, 2, 1, 13000);
INSERT INTO `ads_values` VALUES (7, 2, 2, 150);
INSERT INTO `ads_values` VALUES (8, 2, 3, 2008);
INSERT INTO `ads_values` VALUES (9, 2, 4, 1);
INSERT INTO `ads_values` VALUES (10, 2, 5, 160);
INSERT INTO `ads_values` VALUES (11, 3, 1, 79800);
INSERT INTO `ads_values` VALUES (12, 3, 2, 172);
INSERT INTO `ads_values` VALUES (13, 3, 3, 2008);
INSERT INTO `ads_values` VALUES (14, 3, 4, 2);
INSERT INTO `ads_values` VALUES (15, 3, 5, 178);
INSERT INTO `ads_values` VALUES (16, 4, 1, 56781);
INSERT INTO `ads_values` VALUES (17, 4, 2, 127);
INSERT INTO `ads_values` VALUES (18, 4, 3, 2009);
INSERT INTO `ads_values` VALUES (19, 4, 4, 3);
INSERT INTO `ads_values` VALUES (20, 4, 5, 156);
INSERT INTO `ads_values` VALUES (21, 5, 1, 10200);
INSERT INTO `ads_values` VALUES (22, 5, 2, 205);
INSERT INTO `ads_values` VALUES (23, 5, 3, 2000);
INSERT INTO `ads_values` VALUES (24, 5, 4, 3);
INSERT INTO `ads_values` VALUES (25, 5, 5, 160);
INSERT INTO `ads_values` VALUES (26, 6, 1, 45877);
INSERT INTO `ads_values` VALUES (27, 6, 2, 150);
INSERT INTO `ads_values` VALUES (28, 6, 3, 2009);
INSERT INTO `ads_values` VALUES (29, 6, 4, 1);
INSERT INTO `ads_values` VALUES (30, 6, 5, 168);

我想低于查询结果

ads_id - ads_title - INLIST KEYS /*if into ads_keys table field's value 1 then this rows to columns*/

例如;

+----+-----------+-----------+------------+
| id | ads_title | KM        | YEAR       |  -> If inlist=1 to columns to title 
+----+-----------+-----------+------------+         (looks KM and YEAR inlist=1)
|  1 | AAA       | val       | val        |
|  2 | BBB       | val       | val        |
|  3 | CCC       | val       | val        |
|  4 | DDD       | val       | val        |
|  5 | EEE       | val       | val        |
|  6 | FFF       | val       | val        |
+----+-----------+-----------+------------+

我如何将这一行放到列中?以及我如何过滤此查询。例如颜色=1 或速度=160

编辑:行到列工作正常。谢谢@bluefeet。 我有新的要求。

请参阅http://sqlfiddle.com/#!2/8b74b/12。如何按显示的键过滤过滤器?

4

2 回答 2

7

在 MySQL 中,要将行转换为列,您必须应用聚合函数和 CASE 表达式。

如果已知值的数量有限,则可以对查询进行硬编码:

select a.id,
  a.ads_title,
  max(case when k.`key` ='KM' then v.value end) `KM`,
  max(case when k.`key` ='Year' then v.value end) `Year`
from ads a
left join ads_values v 
  on a.id = v.ads_id
left join ads_keys k
  on v.key_id = k.id
where k.inlist = 1
group by a.id;

请参阅SQL Fiddle with Demo

现在,如果您想根据inlist值更改结果而无需重写查询,那么您可以使用带有动态 SQL 的准备好的语句:

SET @sql = NULL;
set @keyNumber = 1;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(case when k.`key` = ''',
      `key`,
      ''' then v.value end) as `', 
      `key`, '`')
  ) INTO @sql
FROM ads_keys
where inlist = @keyNumber;

SET @sql = CONCAT('SELECT a.id,
                    a.ads_title, ', @sql, ' 
                  from ads a
                  left join ads_values v 
                    on a.id = v.ads_id
                  left join ads_keys k
                    on v.key_id = k.id
                  where k.inlist = ', @keyNumber, '
                  group by a.id');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

请参阅SQL Fiddle with Demo。两个版本都会给出结果:

| ID | ADS_TITLE |    KM | YEAR |
---------------------------------
|  1 |       AAA | 89000 | 2010 |
|  2 |       BBB | 13000 | 2008 |
|  3 |       CCC | 79800 | 2008 |
|  4 |       DDD | 56781 | 2009 |
|  5 |       EEE | 10200 | 2000 |
|  6 |       FFF | 45877 | 2009 |
于 2013-08-09T11:51:26.620 回答
1

由于这也被标记为 PHP,我将首先给你一个 php 的提示。或者,您可以为结果创建一个 mysql 过程或函数。更简单的方法是,如果您的 ads_keys-table 是静态的(那里没有添加更多键),您可以尝试不使用这里的功能

<?
   $d = $db -> getRows('select ads.*, ads_keys.key, ads_values.value from ads, ads_keys, ads_values where ads_keys.inlist = 1 and ads_values.key_id = ads_keys.id and ads_values.ads_id = ads.id');
   $r = $keys = array();
   foreach ($d as $k => $v) {
       if (!isset($r[$v['id']])) {
            $r[$v['id']]= array ('id' => $v['id'], 'ads_title' => $v['ads_title'], $v['key'] => $v['value']);
       } else if (!isset($r[$v['id']][$v['key']])) {
           $r[$v['id']][$v['key']] = $v['value'];
       }

       $keys[] = $v['key'];
   }
   $keys = array_unique($keys);

    echo "id|ads_title|";
    foreach ($keys as $key) {
        echo $key."|";
    }
    echo "\n";
    foreach ($r as $res) {
        echo $res['id']."|";
        echo $res['ads_title']."|";
        foreach ($keys as $key) {
            echo (isset($res[$key]) ? $res[$key] : ' ')."|";
        }

        echo "\n";
    }
?>

结果:

id|ads_title|KM|YEAR|
1|AAA|89000|2010|
2|BBB|13000|2008|
3|CCC|79800|2008|
4|DDD|56781|2009|
5|EEE|10200|2000|
6|FFF|45877|2009|
于 2013-08-09T09:46:13.663 回答