在MySQL中,如何从一个表中获取2列,从一行中的其他表中获取2行作为列?

时间:2013-10-09 15:09:27

标签: php mysql sql subquery prestashop

我知道这很复杂,但我真诚地希望有人能检查一下。 我做了短版(为了更好地理解问题)和完整版(用原始SQL)

简短版本:

[TABLE A] [TABLE B]
|1|a|b|   |1|x
|2|c|d|   |1|y
|3| | |   |2|z
|5| | |   |2|v
          |4|w

如何让MySQL查询以获得类似的行:

1|a|b|x|y
2|c|d|z|v

A中有2列,B中有2列作为列,只有键1和2,没有空结果

子查询?

完整版:

我试图从Prestashop db 连续获取

  • 产品ID
  • ean13代码
  • upc code
  • 功能,ID 24
  • 功能,ID 25

很容易获得id_product,ean13和upc,因为它是ps_product表中的一行。为了获得我使用子查询的功能(JOIN没有用)。

所以,我选择了id_product,ean13,upc,(subquery1)作为code1,(subquery2)作为code2。 然后我需要抛出空行。但不能只将code1或code2放在WHERE中。 为了使它工作,我不得不把所有东西放在子查询中。

此代码 WORKS ,但它非常难看,我打赌这应该以不同的方式完成。

如何才能更好?

SELECT * FROM(
    SELECT 
        p.id_product as idp, p.ean13 as ean13, p.upc as upc, (
            SELECT
                fvl.value
            FROM
                `ps_feature_product` fp
            LEFT JOIN
                `ps_feature_value_lang` fvl ON (fp.id_feature_value = fvl.id_feature_value)
            WHERE fp.id_feature = 24 AND fp.id_product = idp
        ) AS code1, (
            SELECT
                fvl.value
            FROM
                `ps_feature_product` fp
            LEFT JOIN
                `ps_feature_value_lang` fvl ON (fp.id_feature_value = fvl.id_feature_value)
            WHERE fp.id_feature = 25 AND fp.id_product = idp
        ) AS code2,
        m.name
    FROM 
        `ps_product` p 
    LEFT JOIN 
        `ps_manufacturer` m ON (p.id_manufacturer = m.id_manufacturer)
) mainq
WHERE 
    ean13 != '' OR upc != '' OR code1 IS NOT NULL OR code2 IS NOT NULL

4 个答案:

答案 0 :(得分:2)

create table tablea 
( id int,
  col1 varchar(1),
  col2 varchar(1));

create table tableb 
( id int,
  feature int,
  cola varchar(1));

insert into tablea (id, col1, col2)
select 1,'a','b'  union
select 2,'c','d'  union
select 3,null,null  union
select 5,null,null;


insert into tableb (id, feature, cola)
select 1,24,'x'  union
select 1,25,'y' union
select 2,24,'z' union
select 2,25,'v' union
select 4,24,'w';

select a.id, a.col1, a.col2, b1.cola b1a, b2.cola b2a
from tablea a
inner join tableb b1 on (b1.id = a.id and b1.feature = 24)
inner join tableb b2 on (b2.id = a.id and b2.feature = 25);

SQLFiddle here

答案 1 :(得分:0)

您想要做的是Pivot Query。 MySQL没有本地支持数据透视查询,但其他RDBMSen也支持。

您可以使用派生列模拟数据透视查询,但必须指定每个派生列。也就是说,MySQL本身不可能使列数与另一个表的行匹配。这必须提前知道。

将结果作为行查询然后使用PHP进行聚合会更容易。例如:

while ($row = $result->fetch()) {
    if (!isset($table[$row->id])) {
        $table[$row->id] = array();
    }
    $table[$row->id][] = $row->feature;

答案 2 :(得分:0)

这不是一个简单的问题,因为它不是标准查询,顺便说一句,如果您可以使用视图,则可以执行以下过程。假设你是从这些表开始的:

CREATE TABLE `A` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `firstA` char(1) NOT NULL DEFAULT '',
  `secondA` char(1) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
);

CREATE TABLE `B` (
  `id` int(11) unsigned NOT NULL,
  `firstB` char(1) NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `A` (`id`, `firstA`, `secondA`)
VALUES (1, 'a', 'b'), (2, 'c', 'd');

INSERT INTO `B` (`id`, `firstB`)
VALUES (1, 'x'), (1, 'y'), (2, 'z'), (2, 'v'), (4, 'w');

首先创建一个连接两个表的视图:

create or replace view C_join as
select A.firstA, A.secondA, B.firstB
from A
join B on B.id=A.id;

创建对表B中的行进行分组的视图:

create or replace view d_group_concat as
select firstA, secondA, group_concat(firstB) groupconcat
from c_join
group by firstA, secondA

创建满足您需求的视图:

create or replace view e_result as
select firstA, secondA, SUBSTRING_INDEX(groupconcat,',',1) firstB, SUBSTRING_INDEX(SUBSTRING_INDEX(groupconcat,',',2),',',-1) secondB
from d_group_concat

就是这样。希望这会对你有所帮助。

如果您无法创建视图,则可能是查询:

select firstA, secondA, SUBSTRING_INDEX(groupconcat,',',1) firstB, SUBSTRING_INDEX(SUBSTRING_INDEX(groupconcat,',',2),',',-1) secondB
from (
        select firstA, secondA, group_concat(firstB) groupconcat
        from (
                select A.firstA, A.secondA, B.firstB
                from A
                join B on B.id=A.id
        ) c_join
        group by firstA, secondA
) d_group_concat

答案 3 :(得分:0)

非常感谢大家的答案。马克的答案是第一个,最简单,在我的案例中完美无缺。使用子查询,查询运行速度比我的快几倍。谢谢,马克!

我只需要说几句话:

它是Prestashop和批发交换平台的集成组件的一部分。批发商在平台上使用4种产品代码系统(ean13,upc和2个其他系统)。这两个其他产品代码在Prestashop中作为产品功能添加。该商店有数千种产品,平台上有数十万种产品。这就是速度至关重要的原因。

以下是我的问题的完整版的代码。也许有人会觉得这很有帮助。

查询将Prestashop产品代码和某些功能放在一行:

SELECT 
    p.id_product, p.ean13, p.upc, fvl1.value as code1, fvl2.value as code2
FROM `ps_product` p 
LEFT JOIN 
    `ps_feature_product` fp1 ON (p.id_product = fp1.id_product and fp1.id_feature = 24)
LEFT JOIN 
    `ps_feature_value_lang` fvl1 ON (fvl1.id_feature_value = fp1.id_feature_value)
LEFT JOIN 
    `ps_feature_product` fp2 ON (p.id_product = fp2.id_product and fp2.id_feature = 25)
LEFT JOIN 
    `ps_feature_value_lang` fvl2 ON (fvl2.id_feature_value = fp2.id_feature_value)
WHERE 
    ean13 != '' OR upc != '' OR fvl1.value IS NOT NULL OR fvl2.value IS NOT NULL;